* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.diff.tools.fragmented;
+package com.intellij.diff.util;
import com.intellij.openapi.editor.Document;
import org.jetbrains.annotations.NotNull;
public class LineCol {
+ // counting from zero
public final int line;
public final int column;
+ public LineCol(int line) {
+ this(line, 0);
+ }
+
public LineCol(int line, int column) {
this.line = line;
this.column = column;
return isLeft ? LEFT : RIGHT;
}
+ @NotNull
+ public static Side fromRight(boolean isRight) {
+ return isRight ? RIGHT : LEFT;
+ }
+
public int getIndex() {
return myIndex;
}
import com.intellij.diff.tools.binary.BinaryDiffTool;
import com.intellij.diff.tools.dir.DirDiffTool;
import com.intellij.diff.tools.external.ExternalDiffTool;
-import com.intellij.diff.tools.fragmented.OnesideDiffTool;
+import com.intellij.diff.tools.fragmented.UnifiedDiffTool;
import com.intellij.diff.tools.simple.SimpleDiffTool;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
public List<DiffTool> getDiffTools() {
List<DiffTool> result = new ArrayList<DiffTool>();
result.add(SimpleDiffTool.INSTANCE);
- result.add(OnesideDiffTool.INSTANCE);
+ result.add(UnifiedDiffTool.INSTANCE);
result.add(BinaryDiffTool.INSTANCE);
result.add(DirDiffTool.INSTANCE);
Collections.addAll(result, DiffTool.EP_NAME.getExtensions());
import java.util.Iterator;
import java.util.List;
-public class MergeUtil {
+public class ComparisonMergeUtil {
@NotNull
public static List<MergeLineFragment> buildFair(@NotNull FairDiffIterable fragments1,
@NotNull FairDiffIterable fragments2,
import com.intellij.diff.DiffContext;
import com.intellij.diff.FrameDiffTool;
+import com.intellij.diff.requests.ContentDiffRequest;
import com.intellij.diff.requests.DiffRequest;
import org.jetbrains.annotations.NotNull;
@NotNull
@Override
public DiffViewer createComponent(@NotNull DiffContext context, @NotNull DiffRequest request) {
- return new BinaryDiffViewer(context, request);
+ if (OnesideBinaryDiffViewer.canShowRequest(context, request)) return new OnesideBinaryDiffViewer(context, request);
+ if (TwosideBinaryDiffViewer.canShowRequest(context, request)) return new TwosideBinaryDiffViewer(context, request);
+ if (ThreesideBinaryDiffViewer.canShowRequest(context, request)) return new ThreesideBinaryDiffViewer(context, request);
+ throw new IllegalArgumentException(request.toString());
}
@Override
public boolean canShow(@NotNull DiffContext context, @NotNull DiffRequest request) {
- return BinaryDiffViewer.canShowRequest(context, request);
+ return OnesideBinaryDiffViewer.canShowRequest(context, request) ||
+ TwosideBinaryDiffViewer.canShowRequest(context, request) ||
+ ThreesideBinaryDiffViewer.canShowRequest(context, request);
}
@NotNull
+++ /dev/null
-/*
- * Copyright 2000-2015 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.diff.tools.binary;
-
-import com.intellij.diff.DiffContext;
-import com.intellij.diff.actions.impl.FocusOppositePaneAction;
-import com.intellij.diff.contents.DiffContent;
-import com.intellij.diff.contents.DocumentContent;
-import com.intellij.diff.contents.EmptyContent;
-import com.intellij.diff.contents.FileContent;
-import com.intellij.diff.requests.ContentDiffRequest;
-import com.intellij.diff.requests.DiffRequest;
-import com.intellij.diff.tools.util.DiffNotifications;
-import com.intellij.diff.tools.util.FocusTrackerSupport;
-import com.intellij.diff.tools.util.SimpleDiffPanel;
-import com.intellij.diff.tools.util.StatusPanel;
-import com.intellij.diff.tools.util.base.ListenerDiffViewerBase;
-import com.intellij.diff.util.DiffUtil;
-import com.intellij.diff.util.Side;
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.EditorFactory;
-import com.intellij.openapi.fileEditor.FileEditor;
-import com.intellij.openapi.fileEditor.FileEditorProvider;
-import com.intellij.openapi.fileEditor.OpenFileDescriptor;
-import com.intellij.openapi.fileEditor.TextEditor;
-import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager;
-import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
-import com.intellij.openapi.fileTypes.UIBasedFileType;
-import com.intellij.openapi.progress.ProcessCanceledException;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
-import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.Couple;
-import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.CalledInAwt;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-
-public class BinaryDiffViewer extends ListenerDiffViewerBase {
- public static final Logger LOG = Logger.getInstance(BinaryDiffViewer.class);
-
- @NotNull private final SimpleDiffPanel myPanel;
- @NotNull private final BinaryContentPanel myContentPanel;
- @NotNull private final MyStatusPanel myStatusPanel;
-
- @Nullable private final FileEditor myEditor1;
- @Nullable private final FileEditor myEditor2;
- @Nullable private final FileEditorProvider myEditorProvider1;
- @Nullable private final FileEditorProvider myEditorProvider2;
-
- @NotNull private final FocusTrackerSupport.TwosideFocusTrackerSupport myFocusTrackerSupport;
-
- public BinaryDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
- super(context, (ContentDiffRequest)request);
-
- List<JComponent> titlePanel = DiffUtil.createSimpleTitles(myRequest);
- Couple<Pair<FileEditor, FileEditorProvider>> editors = createEditors();
-
- myEditor1 = editors.first.first;
- myEditorProvider1 = editors.first.second;
- myEditor2 = editors.second.first;
- myEditorProvider2 = editors.second.second;
- assert myEditor1 != null || myEditor2 != null;
-
- myFocusTrackerSupport = new FocusTrackerSupport.TwosideFocusTrackerSupport(getEditor1(), getEditor2());
- myContentPanel = new BinaryContentPanel(titlePanel, getEditor1(), getEditor2());
-
- myPanel = new SimpleDiffPanel(myContentPanel, this, context);
-
- myStatusPanel = new MyStatusPanel();
-
- new MyFocusOppositePaneAction().setupAction(myPanel);
- }
-
- @CalledInAwt
- public void onDispose() {
- destroyEditors();
- super.onDispose();
- }
-
- @Override
- @CalledInAwt
- protected void processContextHints() {
- super.processContextHints();
- myFocusTrackerSupport.processContextHints(myRequest, myContext);
- }
-
- @Override
- @CalledInAwt
- protected void updateContextHints() {
- super.updateContextHints();
- myFocusTrackerSupport.updateContextHints(myRequest, myContext);
- }
-
- //
- // Editors
- //
-
- @NotNull
- protected Couple<Pair<FileEditor, FileEditorProvider>> createEditors() {
- List<DiffContent> contents = myRequest.getContents();
-
- Pair<FileEditor, FileEditorProvider> pair1;
- Pair<FileEditor, FileEditorProvider> pair2;
-
- try {
- pair1 = createEditor(contents.get(0));
- pair2 = createEditor(contents.get(1));
- return Couple.of(pair1, pair2);
- }
- catch (IOException e) {
- LOG.error(e);
- Pair<FileEditor, FileEditorProvider> empty = Pair.empty();
- return Couple.of(empty, empty);
- }
- }
-
- @NotNull
- private Pair<FileEditor, FileEditorProvider> createEditor(@NotNull final DiffContent content) throws IOException {
- if (content instanceof EmptyContent) return Pair.empty();
- if (content instanceof FileContent) {
- Project project = myProject != null ? myProject : ProjectManager.getInstance().getDefaultProject();
- VirtualFile file = ((FileContent)content).getFile();
-
- FileEditorProvider[] providers = FileEditorProviderManager.getInstance().getProviders(project, file);
- if (providers.length == 0) throw new IOException("Can't find FileEditorProvider");
-
- FileEditorProvider provider = providers[0];
- FileEditor editor = provider.createEditor(project, file);
-
- UIUtil.removeScrollBorder(editor.getComponent());
-
- return Pair.create(editor, provider);
- }
- if (content instanceof DocumentContent) {
- Document document = ((DocumentContent)content).getDocument();
- final Editor editor = DiffUtil.createEditor(document, myProject, true);
-
- TextEditorProvider provider = TextEditorProvider.getInstance();
- TextEditor fileEditor = provider.getTextEditor(editor);
-
- Disposer.register(fileEditor, new Disposable() {
- @Override
- public void dispose() {
- EditorFactory.getInstance().releaseEditor(editor);
- }
- });
-
- return Pair.<FileEditor, FileEditorProvider>create(fileEditor, provider);
- }
- throw new IllegalArgumentException(content.getClass() + " - " + content.toString());
- }
-
-
- private void destroyEditors() {
- if (getEditor1() != null) {
- assert myEditorProvider1 != null;
- myEditorProvider1.disposeEditor(getEditor1());
- }
- if (getEditor2() != null) {
- assert myEditorProvider2 != null;
- myEditorProvider2.disposeEditor(getEditor2());
- }
- }
-
- //
- // Diff
- //
-
- @Override
- protected void onSlowRediff() {
- super.onSlowRediff();
- myStatusPanel.setBusy(true);
- }
-
- @Override
- @NotNull
- protected Runnable performRediff(@NotNull final ProgressIndicator indicator) {
- try {
- indicator.checkCanceled();
-
- List<DiffContent> contents = myRequest.getContents();
-
- if (contents.get(0) instanceof EmptyContent) {
- return applyNotification(DiffNotifications.INSERTED_CONTENT);
- }
-
- if (contents.get(1) instanceof EmptyContent) {
- return applyNotification(DiffNotifications.REMOVED_CONTENT);
- }
-
- if (!(contents.get(0) instanceof FileContent) || !(contents.get(1) instanceof FileContent)) {
- return applyNotification(null);
- }
-
- final VirtualFile file1 = ((FileContent)contents.get(0)).getFile();
- final VirtualFile file2 = ((FileContent)contents.get(1)).getFile();
- if (!file1.isValid() || !file2.isValid()) {
- return applyNotification(DiffNotifications.ERROR);
- }
-
- final boolean equal = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
- @Override
- public Boolean compute() {
- try {
- // we can't use getInputStream() here because we can't restore BOM marker
- // (getBom() can return null for binary files, while getInputStream() strips BOM for all files).
- // It can be made for files from VFS that implements FileSystemInterface though.
- byte[] bytes1 = file1.contentsToByteArray();
- byte[] bytes2 = file2.contentsToByteArray();
- return Arrays.equals(bytes1, bytes2);
- }
- catch (IOException e) {
- LOG.warn(e);
- return false;
- }
- }
- });
-
- return applyNotification(equal ? DiffNotifications.EQUAL_CONTENTS : null);
- }
- catch (ProcessCanceledException ignore) {
- return applyNotification(DiffNotifications.OPERATION_CANCELED);
- }
- catch (Throwable e) {
- LOG.error(e);
- return applyNotification(DiffNotifications.ERROR);
- }
- }
-
- @NotNull
- private Runnable applyNotification(@Nullable final JComponent notification) {
- return new Runnable() {
- @Override
- public void run() {
- clearDiffPresentation();
- if (notification != null) myPanel.addNotification(notification);
- }
- };
- }
-
- private void clearDiffPresentation() {
- myStatusPanel.setBusy(false);
- myPanel.resetNotifications();
- }
-
- //
- // Getters
- //
-
- @NotNull
- @Override
- public JComponent getComponent() {
- return myPanel;
- }
-
- @Nullable
- @Override
- public JComponent getPreferredFocusedComponent() {
- return getCurrentEditor().getPreferredFocusedComponent();
- }
-
- @NotNull
- public Side getCurrentSide() {
- return myFocusTrackerSupport.getCurrentSide();
- }
-
- public void setCurrentSide(@NotNull Side side) {
- myFocusTrackerSupport.setCurrentSide(side);
- }
-
- @Nullable
- FileEditor getEditor2() {
- return myEditor2;
- }
-
- @Nullable
- FileEditor getEditor1() {
- return myEditor1;
- }
-
- @NotNull
- FileEditor getCurrentEditor() {
- //noinspection ConstantConditions
- return getCurrentSide().select(getEditor1(), getEditor2());
- }
-
- @NotNull
- @Override
- protected JComponent getStatusPanel() {
- return myStatusPanel;
- }
-
- //
- // Misc
- //
-
- @Nullable
- @Override
- protected OpenFileDescriptor getOpenFileDescriptor() {
- return getCurrentSide().selectNotNull(getRequest().getContents()).getOpenFileDescriptor();
- }
-
- public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
- if (!(request instanceof ContentDiffRequest)) return false;
-
- List<DiffContent> contents = ((ContentDiffRequest)request).getContents();
- if (contents.size() != 2) return false;
-
- boolean canShow = true;
- boolean wantShow = false;
- for (DiffContent content : contents) {
- canShow &= canShowContent(content, context);
- wantShow |= wantShowContent(content, context);
- }
- return canShow && wantShow;
- }
-
- public static boolean canShowContent(@NotNull DiffContent content, @NotNull DiffContext context) {
- if (content instanceof EmptyContent) return true;
- if (content instanceof DocumentContent) return true;
- if (content instanceof FileContent) {
- Project project = context.getProject();
- if (project == null) project = ProjectManager.getInstance().getDefaultProject();
- VirtualFile file = ((FileContent)content).getFile();
-
- return FileEditorProviderManager.getInstance().getProviders(project, file).length != 0;
- }
- return false;
- }
-
- public static boolean wantShowContent(@NotNull DiffContent content, @NotNull DiffContext context) {
- if (content instanceof EmptyContent) return false;
- if (content instanceof FileContent) {
- if (content.getContentType() == null) return false;
- if (content.getContentType().isBinary()) return true;
- if (content.getContentType() instanceof UIBasedFileType) return true;
- return false;
- }
- return false;
- }
-
- //
- // Actions
- //
-
- private class MyFocusOppositePaneAction extends FocusOppositePaneAction {
- @Override
- public void actionPerformed(@NotNull AnActionEvent e) {
- assert getEditor1() != null && getEditor2() != null;
- setCurrentSide(getCurrentSide().other());
- myContext.requestFocus();
- }
-
- @Override
- public void update(@NotNull AnActionEvent e) {
- e.getPresentation().setEnabled(getEditor1() != null && getEditor2() != null);
- }
- }
-
- //
- // Helpers
- //
-
- @Nullable
- @Override
- public Object getData(@NonNls String dataId) {
- if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) {
- return DiffUtil.getVirtualFile(myRequest, getCurrentSide());
- }
- return super.getData(dataId);
- }
-
- private static class MyStatusPanel extends StatusPanel {
- @Override
- protected int getChangesCount() {
- return -1;
- }
- }
-}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.binary;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.requests.ContentDiffRequest;
+import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.holders.BinaryEditorHolder;
+import com.intellij.diff.tools.util.DiffNotifications;
+import com.intellij.diff.tools.util.side.OnesideDiffViewer;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.progress.ProgressIndicator;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class OnesideBinaryDiffViewer extends OnesideDiffViewer<BinaryEditorHolder> {
+ public static final Logger LOG = Logger.getInstance(OnesideBinaryDiffViewer.class);
+
+ public OnesideBinaryDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ super(context, (ContentDiffRequest)request, BinaryEditorHolder.BinaryEditorHolderFactory.INSTANCE);
+ }
+
+ //
+ // Diff
+ //
+
+ @Override
+ @NotNull
+ protected Runnable performRediff(@NotNull final ProgressIndicator indicator) {
+ JComponent notification = getSide().select(DiffNotifications.REMOVED_CONTENT, DiffNotifications.INSERTED_CONTENT);
+ return applyNotification(notification);
+ }
+
+ @NotNull
+ private Runnable applyNotification(@Nullable final JComponent notification) {
+ return new Runnable() {
+ @Override
+ public void run() {
+ clearDiffPresentation();
+ if (notification != null) myPanel.addNotification(notification);
+ }
+ };
+ }
+
+ private void clearDiffPresentation() {
+ myPanel.resetNotifications();
+ }
+
+ //
+ // Getters
+ //
+
+ @NotNull
+ FileEditor getEditor() {
+ return getEditorHolder().getEditor();
+ }
+
+ //
+ // Misc
+ //
+
+ public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ return OnesideDiffViewer.canShowRequest(context, request, BinaryEditorHolder.BinaryEditorHolderFactory.INSTANCE);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.binary;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.requests.ContentDiffRequest;
+import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.holders.BinaryEditorHolder;
+import com.intellij.diff.tools.util.side.ThreesideDiffViewer;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.util.EmptyRunnable;
+import org.jetbrains.annotations.NotNull;
+
+public class ThreesideBinaryDiffViewer extends ThreesideDiffViewer<BinaryEditorHolder> {
+ public ThreesideBinaryDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ super(context, (ContentDiffRequest)request, BinaryEditorHolder.BinaryEditorHolderFactory.INSTANCE);
+ }
+
+ @Override
+ @NotNull
+ protected Runnable performRediff(@NotNull final ProgressIndicator indicator) {
+ return EmptyRunnable.INSTANCE;
+ }
+
+ public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ return ThreesideDiffViewer.canShowRequest(context, request, BinaryEditorHolder.BinaryEditorHolderFactory.INSTANCE);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.binary;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.actions.impl.FocusOppositePaneAction;
+import com.intellij.diff.contents.DiffContent;
+import com.intellij.diff.contents.FileContent;
+import com.intellij.diff.requests.ContentDiffRequest;
+import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.holders.BinaryEditorHolder;
+import com.intellij.diff.tools.util.DiffNotifications;
+import com.intellij.diff.tools.util.StatusPanel;
+import com.intellij.diff.tools.util.side.TwosideDiffViewer;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+public class TwosideBinaryDiffViewer extends TwosideDiffViewer<BinaryEditorHolder> {
+ public static final Logger LOG = Logger.getInstance(TwosideBinaryDiffViewer.class);
+
+ @NotNull private final StatusPanel myStatusPanel;
+
+ public TwosideBinaryDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ super(context, (ContentDiffRequest)request, BinaryEditorHolder.BinaryEditorHolderFactory.INSTANCE);
+
+ myStatusPanel = new StatusPanel();
+ new MyFocusOppositePaneAction().setupAction(myPanel);
+ }
+
+ //
+ // Diff
+ //
+
+ @Override
+ protected void onSlowRediff() {
+ super.onSlowRediff();
+ myStatusPanel.setBusy(true);
+ }
+
+ @Override
+ @NotNull
+ protected Runnable performRediff(@NotNull final ProgressIndicator indicator) {
+ try {
+ indicator.checkCanceled();
+
+ List<DiffContent> contents = myRequest.getContents();
+ if (!(contents.get(0) instanceof FileContent) || !(contents.get(1) instanceof FileContent)) {
+ return applyNotification(null);
+ }
+
+ final VirtualFile file1 = ((FileContent)contents.get(0)).getFile();
+ final VirtualFile file2 = ((FileContent)contents.get(1)).getFile();
+ if (!file1.isValid() || !file2.isValid()) {
+ return applyNotification(DiffNotifications.ERROR);
+ }
+
+ final boolean equal = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ try {
+ // we can't use getInputStream() here because we can't restore BOM marker
+ // (getBom() can return null for binary files, while getInputStream() strips BOM for all files).
+ // It can be made for files from VFS that implements FileSystemInterface though.
+ byte[] bytes1 = file1.contentsToByteArray();
+ byte[] bytes2 = file2.contentsToByteArray();
+ return Arrays.equals(bytes1, bytes2);
+ }
+ catch (IOException e) {
+ LOG.warn(e);
+ return false;
+ }
+ }
+ });
+
+ return applyNotification(equal ? DiffNotifications.EQUAL_CONTENTS : null);
+ }
+ catch (ProcessCanceledException e) {
+ throw e;
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ return applyNotification(DiffNotifications.ERROR);
+ }
+ }
+
+ @NotNull
+ private Runnable applyNotification(@Nullable final JComponent notification) {
+ return new Runnable() {
+ @Override
+ public void run() {
+ clearDiffPresentation();
+ if (notification != null) myPanel.addNotification(notification);
+ }
+ };
+ }
+
+ private void clearDiffPresentation() {
+ myStatusPanel.setBusy(false);
+ myPanel.resetNotifications();
+ }
+
+ //
+ // Getters
+ //
+
+ @NotNull
+ FileEditor getCurrentEditor() {
+ return getCurrentEditorHolder().getEditor();
+ }
+
+ @NotNull
+ @Override
+ protected JComponent getStatusPanel() {
+ return myStatusPanel;
+ }
+
+ //
+ // Misc
+ //
+
+ public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ return TwosideDiffViewer.canShowRequest(context, request, BinaryEditorHolder.BinaryEditorHolderFactory.INSTANCE);
+ }
+
+ //
+ // Actions
+ //
+
+ private class MyFocusOppositePaneAction extends FocusOppositePaneAction {
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent e) {
+ setCurrentSide(getCurrentSide().other());
+ myContext.requestFocus();
+ }
+ }
+}
import com.intellij.diff.fragments.LineFragmentImpl;
import org.jetbrains.annotations.NotNull;
-public class ChangedBlock {
+class ChangedBlock {
private final int myStartOffset1;
private final int myEndOffset1;
private final int myStartOffset2;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.NotNull;
-public class HighlightRange {
+class HighlightRange {
@NotNull private final TextRange myBase;
@NotNull private final TextRange myChanged;
@NotNull private final Side mySide;
import java.util.Map;
import java.util.TreeMap;
-public class LineNumberConvertor {
+class LineNumberConvertor {
// Oneside -> Twoside
@NotNull private final TreeMap<Integer, Integer> myFragments1;
@NotNull private final TreeMap<Integer, Integer> myFragments2;
public LineNumberConvertor build() {
return new LineNumberConvertor(myFragments1, myFragments2, myInvertedFragments1, myInvertedFragments2);
}
-
- @NotNull
- public static LineNumberConvertor createLeft(int lines) {
- Builder builder = new Builder();
- builder.put1(0, 0, lines);
- return builder.build();
- }
-
- @NotNull
- public static LineNumberConvertor createRight(int lines) {
- Builder builder = new Builder();
- builder.put2(0, 0, lines);
- return builder.build();
- }
}
/*
import java.awt.*;
import java.util.List;
-public class OnesideContentPanel extends JPanel {
- public OnesideContentPanel(@NotNull List<JComponent> titles, @NotNull Editor editor) {
+class UnifiedContentPanel extends JPanel {
+ public UnifiedContentPanel(@NotNull List<JComponent> titles, @NotNull Editor editor) {
super(new BorderLayout());
add(editor.getComponent(), BorderLayout.CENTER);
import com.intellij.diff.fragments.LineFragment;
import com.intellij.diff.util.DiffDrawUtil;
import com.intellij.diff.util.DiffUtil;
+import com.intellij.diff.util.DiffUtil.UpdatedLineRange;
import com.intellij.diff.util.Side;
import com.intellij.diff.util.TextDiffType;
import com.intellij.icons.AllIcons;
import java.util.ArrayList;
import java.util.List;
-public class OnesideDiffChange {
- @NotNull private final OnesideDiffViewer myViewer;
+public class UnifiedDiffChange {
+ @NotNull private final UnifiedDiffViewer myViewer;
@NotNull private final EditorEx myEditor;
// Boundaries of this change in myEditor. If current state is out-of-date - approximate value.
@NotNull private final List<RangeHighlighter> myHighlighters = new ArrayList<RangeHighlighter>();
@NotNull private final List<MyGutterOperation> myOperations = new ArrayList<MyGutterOperation>();
- public OnesideDiffChange(@NotNull OnesideDiffViewer viewer, @NotNull ChangedBlock block, boolean innerFragments) {
+ public UnifiedDiffChange(@NotNull UnifiedDiffViewer viewer, @NotNull ChangedBlock block, boolean innerFragments) {
myViewer = viewer;
myEditor = viewer.getEditor();
}
private void doInstallActionHighlighters() {
- if (myViewer.getDocument(Side.LEFT) == null || myViewer.getDocument(Side.RIGHT) == null) return;
-
boolean leftEditable = myViewer.isEditable(Side.LEFT, false);
boolean rightEditable = myViewer.isEditable(Side.RIGHT, false);
}
public void processChange(int oldLine1, int oldLine2, int shift) {
- if (myLine2 <= oldLine1) return;
- if (myLine1 >= oldLine2) {
- myLine1 += shift;
- myLine2 += shift;
- return;
- }
-
- if (myLine1 <= oldLine1 && myLine2 >= oldLine2) {
- myLine2 += shift;
- return;
- }
-
- // range is destroyed. We don't know new boundaries.
- // Anything below is just a guess in attempt to keep changes ordered.
- int newLine2 = oldLine2 + shift;
- if (myLine2 < oldLine2) {
- if (myLine2 > newLine2) myLine2 = newLine2;
- }
- else {
- myLine2 += shift; // end of change is outside of modified range - just shift
- }
-
- if (myLine1 < oldLine1) myLine1 = Math.min(myLine1, newLine2);
- if (myLine1 > myLine2) myLine1 = myLine2;
+ UpdatedLineRange newRange = DiffUtil.updateRangeOnModification(myLine1, myLine2, oldLine1, oldLine2, shift);
+ myLine1 = newRange.startLine;
+ myLine2 = newRange.endLine;
}
//
public void actionPerformed(AnActionEvent e) {
final Project project = e.getProject();
final Document document = myViewer.getDocument(sourceSide.other());
- assert document != null;
DiffUtil.executeWriteCommand(document, project, "Replace change", new Runnable() {
@Override
public void run() {
- myViewer.applyChange(OnesideDiffChange.this, sourceSide);
+ myViewer.applyChange(UnifiedDiffChange.this, sourceSide);
}
});
// applyChange() will schedule rediff, but we want to try to do it in sync
import com.intellij.diff.comparison.DiffTooBigException;
import com.intellij.diff.tools.util.base.DiffPanelBase;
import com.intellij.openapi.actionSystem.DataProvider;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.util.ui.AsyncProcessIcon;
import org.jetbrains.annotations.NotNull;
import static com.intellij.diff.util.DiffUtil.createMessagePanel;
-public class OnesideDiffPanel extends DiffPanelBase {
+public class UnifiedDiffPanel extends DiffPanelBase {
private static final String GOOD_CONTENT = "GoodContent";
private static final String LOADING_CONTENT = "LoadingContent";
private static final String TOO_BIG_CONTENT = "TooBigContent";
@NotNull private final AsyncProcessIcon.Big myBusyIcon;
- public OnesideDiffPanel(@Nullable Project project,
- @NotNull OnesideContentPanel content,
+ public UnifiedDiffPanel(@Nullable Project project,
+ @NotNull UnifiedContentPanel content,
@NotNull DataProvider provider,
@NotNull DiffContext context) {
super(project, provider, context);
- myBusyIcon = new AsyncProcessIcon.Big("OnesideDiff");
+ myBusyIcon = new AsyncProcessIcon.Big("UnifiedDiff");
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(myNotificationsPanel, BorderLayout.NORTH);
import com.intellij.diff.DiffContext;
import com.intellij.diff.FrameDiffTool;
import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.simple.SimpleOnesideDiffViewer;
import org.jetbrains.annotations.NotNull;
-public class OnesideDiffTool implements FrameDiffTool {
- public static final OnesideDiffTool INSTANCE = new OnesideDiffTool();
+public class UnifiedDiffTool implements FrameDiffTool {
+ public static final UnifiedDiffTool INSTANCE = new UnifiedDiffTool();
@NotNull
@Override
public DiffViewer createComponent(@NotNull DiffContext context, @NotNull DiffRequest request) {
- return new OnesideDiffViewer(context, request);
+ if (SimpleOnesideDiffViewer.canShowRequest(context, request)) return new SimpleOnesideDiffViewer(context, request);
+ if (UnifiedDiffViewer.canShowRequest(context, request)) return new UnifiedDiffViewer(context, request);
+ throw new IllegalArgumentException(request.toString());
}
@Override
public boolean canShow(@NotNull DiffContext context, @NotNull DiffRequest request) {
- return OnesideDiffViewer.canShowRequest(context, request);
+ return SimpleOnesideDiffViewer.canShowRequest(context, request) || UnifiedDiffViewer.canShowRequest(context, request);
}
@NotNull
import com.intellij.diff.actions.DocumentFragmentContent;
import com.intellij.diff.actions.NavigationContextChecker;
import com.intellij.diff.actions.impl.OpenInEditorWithMouseAction;
+import com.intellij.diff.actions.impl.SetEditorSettingsAction;
import com.intellij.diff.comparison.DiffTooBigException;
-import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.contents.DocumentContent;
import com.intellij.diff.fragments.LineFragment;
import com.intellij.diff.requests.ContentDiffRequest;
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.base.IgnorePolicy;
-import com.intellij.diff.tools.util.base.InitialScrollPositionSupport;
-import com.intellij.diff.tools.util.base.TextDiffViewerBase;
-import com.intellij.diff.tools.util.twoside.TwosideTextDiffViewer;
-import com.intellij.diff.util.DiffUserDataKeys;
+import com.intellij.diff.tools.util.base.*;
+import com.intellij.diff.tools.util.side.TwosideTextDiffViewer;
+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.LineRange;
-import com.intellij.diff.util.Side;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UserDataHolder;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.text.MergingCharSequence;
import gnu.trove.TIntFunction;
import org.jetbrains.annotations.*;
import static com.intellij.diff.util.DiffUtil.getLineCount;
-public class OnesideDiffViewer extends TextDiffViewerBase {
- public static final Logger LOG = Logger.getInstance(OnesideDiffViewer.class);
+public class UnifiedDiffViewer extends ListenerDiffViewerBase {
+ public static final Logger LOG = Logger.getInstance(UnifiedDiffViewer.class);
@NotNull protected final EditorEx myEditor;
@NotNull protected final Document myDocument;
- @NotNull private final OnesideDiffPanel myPanel;
+ @NotNull private final UnifiedDiffPanel myPanel;
- @Nullable private final DocumentContent myActualContent1;
- @Nullable private final DocumentContent myActualContent2;
-
- @NotNull private final MySetEditorSettingsAction myEditorSettingsAction;
+ @NotNull private final SetEditorSettingsAction myEditorSettingsAction;
@NotNull private final PrevNextDifferenceIterable myPrevNextDifferenceIterable;
@NotNull private final MyStatusPanel myStatusPanel;
private boolean myStateIsOutOfDate; // whether something was changed since last rediff
private boolean mySuppressEditorTyping; // our state is inconsistent. No typing can be handled correctly
- public OnesideDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ public UnifiedDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
super(context, (ContentDiffRequest)request);
myPrevNextDifferenceIterable = new MyPrevNextDifferenceIterable();
myStatusPanel = new MyStatusPanel();
- myForceReadOnlyFlags = checkForceReadOnly();
-
-
- List<DiffContent> contents = myRequest.getContents();
- myActualContent1 = contents.get(0) instanceof DocumentContent ? ((DocumentContent)contents.get(0)) : null;
- myActualContent2 = contents.get(1) instanceof DocumentContent ? ((DocumentContent)contents.get(1)) : null;
- assert myActualContent1 != null || myActualContent2 != null;
-
- if (myActualContent1 == null) myMasterSide = Side.RIGHT;
- if (myActualContent2 == null) myMasterSide = Side.LEFT;
+ myForceReadOnlyFlags = TextDiffViewerUtil.checkForceReadOnly(myContext, myRequest);
boolean leftEditable = isEditable(Side.LEFT, false);
boolean rightEditable = isEditable(Side.RIGHT, false);
myEditor = DiffUtil.createEditor(myDocument, myProject, true, true);
List<JComponent> titles = DiffUtil.createTextTitles(myRequest, ContainerUtil.list(myEditor, myEditor));
- OnesideContentPanel contentPanel = new OnesideContentPanel(titles, myEditor);
+ UnifiedContentPanel contentPanel = new UnifiedContentPanel(titles, myEditor);
- myPanel = new OnesideDiffPanel(myProject, contentPanel, this, myContext);
+ myPanel = new UnifiedDiffPanel(myProject, contentPanel, this, myContext);
myFoldingModel = new MyFoldingModel(myEditor, this);
- myEditorSettingsAction = new MySetEditorSettingsAction();
+ myEditorSettingsAction = new SetEditorSettingsAction(getTextSettings(), getEditors());
myEditorSettingsAction.applyDefaults();
new MyOpenInEditorWithMouseAction().register(getEditors());
+
+ TextDiffViewerUtil.checkDifferentDocuments(myRequest);
}
@Override
@CalledInAwt
protected void onInit() {
super.onInit();
+ installEditorListeners();
installTypingSupport();
myPanel.setLoadingContent(); // We need loading panel only for initial rediff()
}
protected void processContextHints() {
super.processContextHints();
Side side = DiffUtil.getUserData(myRequest, myContext, DiffUserDataKeys.MASTER_SIDE);
- if (side != null && side.select(myActualContent1, myActualContent2) != null) myMasterSide = side;
+ if (side != null) myMasterSide = side;
myInitialScrollHelper.processContext(myRequest);
}
return group;
}
+ @NotNull
+ protected List<AnAction> createEditorPopupActions() {
+ return TextDiffViewerUtil.createEditorPopupActions();
+ }
+
+ @CalledInAwt
+ protected void installEditorListeners() {
+ new TextDiffViewerUtil.EditorActionsPopup(createEditorPopupActions()).install(getEditors());
+ }
+
//
// Diff
//
protected Runnable performRediff(@NotNull final ProgressIndicator indicator) {
try {
indicator.checkCanceled();
- assert myActualContent1 != null || myActualContent2 != null;
-
- if (myActualContent1 == null) {
- final DocumentContent content = myActualContent2;
- final Document document = content.getDocument();
-
- OnesideDocumentData data = ApplicationManager.getApplication().runReadAction(new Computable<OnesideDocumentData>() {
- @Override
- public OnesideDocumentData compute() {
- EditorHighlighter highlighter = DiffUtil.createEditorHighlighter(myProject, content);
- OnesideEditorRangeHighlighter rangeHighlighter = new OnesideEditorRangeHighlighter(myProject, content.getDocument());
- return new OnesideDocumentData(document.getImmutableCharSequence(), getLineCount(document), highlighter, rangeHighlighter);
- }
- });
-
- List<ChangedBlock> blocks = new ArrayList<ChangedBlock>();
- blocks.add(ChangedBlock.createInserted(data.getText().length() + 1, data.getLines()));
-
- indicator.checkCanceled();
- LineNumberConvertor convertor = LineNumberConvertor.Builder.createRight(data.getLines());
-
- CombinedEditorData editorData = new CombinedEditorData(new MergingCharSequence(data.getText(), "\n"), data.getHighlighter(),
- data.getRangeHighlighter(), content.getContentType(),
- convertor.createConvertor1(), null);
-
- return apply(editorData, blocks, convertor, Collections.singletonList(new LineRange(0, data.getLines())), false, false);
- }
-
- if (myActualContent2 == null) {
- final DocumentContent content = myActualContent1;
- final Document document = content.getDocument();
-
- OnesideDocumentData data = ApplicationManager.getApplication().runReadAction(new Computable<OnesideDocumentData>() {
- @Override
- public OnesideDocumentData compute() {
- EditorHighlighter highlighter = DiffUtil.createEditorHighlighter(myProject, content);
- OnesideEditorRangeHighlighter rangeHighlighter = new OnesideEditorRangeHighlighter(myProject, content.getDocument());
- return new OnesideDocumentData(document.getImmutableCharSequence(), getLineCount(document), highlighter, rangeHighlighter);
- }
- });
-
- List<ChangedBlock> blocks = new ArrayList<ChangedBlock>();
- blocks.add(ChangedBlock.createDeleted(data.getText().length() + 1, data.getLines()));
-
- indicator.checkCanceled();
- LineNumberConvertor convertor = LineNumberConvertor.Builder.createLeft(data.getLines());
-
- CombinedEditorData editorData = new CombinedEditorData(new MergingCharSequence(data.getText(), "\n"), data.getHighlighter(),
- data.getRangeHighlighter(), content.getContentType(),
- convertor.createConvertor2(), null);
-
- return apply(editorData, blocks, convertor, Collections.singletonList(new LineRange(0, data.getLines())), false, false);
- }
- final DocumentContent content1 = myActualContent1;
- final DocumentContent content2 = myActualContent2;
- final Document document1 = content1.getDocument();
- final Document document2 = content2.getDocument();
+ final Document document1 = getContent1().getDocument();
+ final Document document2 = getContent2().getDocument();
final DocumentData documentData = ApplicationManager.getApplication().runReadAction(new Computable<DocumentData>() {
@Override
final boolean innerFragments = getDiffConfig().innerFragments;
final List<LineFragment> fragments = DiffUtil.compareWithCache(myRequest, documentData, getDiffConfig(), indicator);
+ final DocumentContent content1 = getContent1();
+ final DocumentContent content2 = getContent2();
+
indicator.checkCanceled();
TwosideDocumentData data = ApplicationManager.getApplication().runReadAction(new Computable<TwosideDocumentData>() {
@Override
public TwosideDocumentData compute() {
indicator.checkCanceled();
- OnesideFragmentBuilder builder = new OnesideFragmentBuilder(fragments, document1, document2, myMasterSide);
+ UnifiedFragmentBuilder builder = new UnifiedFragmentBuilder(fragments, document1, document2, myMasterSide);
builder.exec();
indicator.checkCanceled();
documentData.getText1(), documentData.getText2(), builder.getRanges(),
builder.getText().length());
- OnesideEditorRangeHighlighter rangeHighlighter = new OnesideEditorRangeHighlighter(myProject, document1, document2,
+ UnifiedEditorRangeHighlighter rangeHighlighter = new UnifiedEditorRangeHighlighter(myProject, document1, document2,
builder.getRanges());
return new TwosideDocumentData(builder, highlighter, rangeHighlighter);
}
});
- OnesideFragmentBuilder builder = data.getBuilder();
+ UnifiedFragmentBuilder builder = data.getBuilder();
FileType fileType = content2.getContentType() == null ? content1.getContentType() : content2.getContentType();
return apply(editorData, builder.getBlocks(), convertor, changedLines, isEqual, innerFragments);
}
- catch (DiffTooBigException ignore) {
+ catch (DiffTooBigException e) {
return new Runnable() {
@Override
public void run() {
}
};
}
- catch (ProcessCanceledException ignore) {
- return new Runnable() {
- @Override
- public void run() {
- clearDiffPresentation();
- myPanel.setOperationCanceledContent();
- }
- };
+ catch (ProcessCanceledException e) {
+ throw e;
}
catch (Throwable e) {
LOG.error(e);
protected void markStateIsOutOfDate() {
myStateIsOutOfDate = true;
if (myChangedBlockData != null) {
- for (OnesideDiffChange diffChange : myChangedBlockData.getDiffChanges()) {
+ for (UnifiedDiffChange diffChange : myChangedBlockData.getDiffChanges()) {
diffChange.updateGutterActions();
}
}
if (highlighter1 == null) highlighter1 = DiffUtil.initEmptyEditorHighlighter(project, text1);
if (highlighter2 == null) highlighter2 = DiffUtil.initEmptyEditorHighlighter(project, text2);
- return new OnesideEditorHighlighter(myDocument, highlighter1, highlighter2, ranges, textLength);
+ return new UnifiedEditorHighlighter(myDocument, highlighter1, highlighter2, ranges, textLength);
}
@NotNull
if (data.getRangeHighlighter() != null) data.getRangeHighlighter().apply(myProject, myDocument);
- ArrayList<OnesideDiffChange> diffChanges = new ArrayList<OnesideDiffChange>(blocks.size());
+ ArrayList<UnifiedDiffChange> diffChanges = new ArrayList<UnifiedDiffChange>(blocks.size());
for (ChangedBlock block : blocks) {
- diffChanges.add(new OnesideDiffChange(OnesideDiffViewer.this, block, innerFragments));
+ diffChanges.add(new UnifiedDiffChange(UnifiedDiffViewer.this, block, innerFragments));
}
List<RangeMarker> guarderRangeBlocks = new ArrayList<RangeMarker>();
}
@Contract("!null, _ -> !null")
- private static TIntFunction mergeConverters(@Nullable final TIntFunction convertor, @NotNull final TIntFunction separatorLines) {
- if (convertor == null) return null;
+ private static TIntFunction mergeConverters(@NotNull final TIntFunction convertor, @NotNull final TIntFunction separatorLines) {
return new TIntFunction() {
@Override
public int execute(int value) {
int[] lines = new int[2];
if (myChangedBlockData == null) {
- lines[0] = myActualContent1 != null ? line : 0;
- lines[1] = myActualContent2 != null ? line : 0;
+ lines[0] = line;
+ lines[1] = line;
return Pair.create(lines, myMasterSide);
}
private void destroyChangedBlockData() {
if (myChangedBlockData == null) return;
- for (OnesideDiffChange change : myChangedBlockData.getDiffChanges()) {
+ for (UnifiedDiffChange change : myChangedBlockData.getDiffChanges()) {
change.destroyHighlighter();
}
for (RangeMarker block : myChangedBlockData.getGuardedRangeBlocks()) {
}
myChangedBlockData = null;
- OnesideEditorRangeHighlighter.erase(myProject, myDocument);
+ UnifiedEditorRangeHighlighter.erase(myProject, myDocument);
myFoldingModel.destroy();
myDuringTwosideDocumentModification = true;
Document twosideDocument = getDocument(myMasterSide);
- assert twosideDocument != null;
- int offset1 = e.getOffset();
- int offset2 = e.getOffset() + e.getOldLength();
+ LineCol onesideStartPosition = LineCol.fromOffset(myDocument, e.getOffset());
+ LineCol onesideEndPosition = LineCol.fromOffset(myDocument, e.getOffset() + e.getOldLength());
- if (StringUtil.endsWithChar(e.getOldFragment(), '\n') &&
- StringUtil.endsWithChar(e.getNewFragment(), '\n')) {
- offset2--;
- }
-
- LineCol onesideStartPosition = LineCol.fromOffset(myDocument, offset1);
- LineCol onesideEndPosition = LineCol.fromOffset(myDocument, offset2);
- int shift = StringUtil.countNewLines(e.getNewFragment()) - StringUtil.countNewLines(e.getOldFragment());
+ int line1 = onesideStartPosition.line;
+ int line2 = onesideEndPosition.line + 1;
+ int shift = DiffUtil.countLinesShift(e);
int twosideStartLine = transferLineFromOnesideStrict(myMasterSide, onesideStartPosition.line);
int twosideEndLine = transferLineFromOnesideStrict(myMasterSide, onesideEndPosition.line);
int twosideEndOffset = twosideDocument.getLineStartOffset(twosideEndLine) + onesideEndPosition.column;
twosideDocument.replaceString(twosideStartOffset, twosideEndOffset, e.getNewFragment());
- for (OnesideDiffChange change : myChangedBlockData.getDiffChanges()) {
- change.processChange(onesideStartPosition.line, onesideEndPosition.line + 1, shift);
+ for (UnifiedDiffChange change : myChangedBlockData.getDiffChanges()) {
+ change.processChange(line1, line2, shift);
}
LineNumberConvertor lineNumberConvertor = myChangedBlockData.getLineNumberConvertor();
- lineNumberConvertor.handleOnesideChange(onesideStartPosition.line, onesideEndPosition.line + 1, shift, myMasterSide);
+ lineNumberConvertor.handleOnesideChange(line1, line2, shift, myMasterSide);
}
finally {
// TODO: we can avoid marking state out-of-date in some simple cases (like in SimpleDiffViewer)
Document document2 = getDocument(Side.RIGHT);
info.append("==== OnesideDiffViewer Debug Info ====");
info.append("myMasterSide - ").append(myMasterSide).append('\n');
- info.append("myLeftDocument.length() - ").append(document1 != null ? document1.getTextLength() : null).append('\n');
- info.append("myRightDocument.length() - ").append(document2 != null ? document2.getTextLength() : null).append('\n');
+ info.append("myLeftDocument.length() - ").append(document1.getTextLength()).append('\n');
+ info.append("myRightDocument.length() - ").append(document2.getTextLength()).append('\n');
info.append("myDocument.length() - ").append(myDocument.getTextLength()).append('\n');
info.append("e.getOffset() - ").append(e.getOffset()).append('\n');
info.append("e.getNewLength() - ").append(e.getNewLength()).append('\n');
}
@CalledWithWriteLock
- public void applyChange(@NotNull OnesideDiffChange change, @NotNull Side sourceSide) {
+ public void applyChange(@NotNull UnifiedDiffChange change, @NotNull Side sourceSide) {
if (myStateIsOutOfDate || myChangedBlockData == null) return;
Side affectedSide = sourceSide.other();
Document document1 = getDocument(Side.LEFT);
Document document2 = getDocument(Side.RIGHT);
- assert document1 != null && document2 != null;
LineFragment lineFragment = change.getLineFragment();
// Impl
//
+
+ @NotNull
+ public TextDiffSettingsHolder.TextDiffSettings getTextSettings() {
+ return TextDiffViewerUtil.getTextSettings(myContext);
+ }
+
+ @NotNull
+ public FoldingModelSupport.Settings getFoldingModelSettings() {
+ return TextDiffViewerUtil.getFoldingModelSettings(myContext);
+ }
+
@NotNull
private DiffUtil.DiffConfig getDiffConfig() {
return new DiffUtil.DiffConfig(getIgnorePolicy(), getHighlightPolicy());
}
@NotNull
- @Override
protected List<? extends EditorEx> getEditors() {
return Collections.singletonList(myEditor);
}
+ @NotNull
+ protected List<? extends DocumentContent> getContents() {
+ //noinspection unchecked
+ return (List<? extends DocumentContent>)(List)myRequest.getContents();
+ }
+
+ @NotNull
+ protected DocumentContent getContent(@NotNull Side side) {
+ return side.select(getContents());
+ }
+
+ @NotNull
+ protected DocumentContent getContent1() {
+ return getContent(Side.LEFT);
+ }
+
+ @NotNull
+ protected DocumentContent getContent2() {
+ return getContent(Side.RIGHT);
+ }
+
@CalledInAwt
@Nullable
- protected List<OnesideDiffChange> getDiffChanges() {
+ protected List<UnifiedDiffChange> getDiffChanges() {
return myChangedBlockData == null ? null : myChangedBlockData.getDiffChanges();
}
public boolean isEditable(@NotNull Side side, boolean respectReadOnlyLock) {
if (myReadOnlyLockSet && respectReadOnlyLock) return false;
if (side.select(myForceReadOnlyFlags)) return false;
- Document document = getDocument(side);
- return document != null && DiffUtil.canMakeWritable(document);
+ return DiffUtil.canMakeWritable(getDocument(side));
}
- @Nullable
+ @NotNull
public Document getDocument(@NotNull Side side) {
- DocumentContent content = side.select(myActualContent1, myActualContent2);
- return content != null ? content.getDocument() : null;
+ return getContent(side).getDocument();
}
protected boolean isStateIsOutOfDate() {
@CalledInAwt
@Nullable
- protected OnesideDiffChange getCurrentChange() {
+ protected UnifiedDiffChange getCurrentChange() {
if (myChangedBlockData == null) return null;
int caretLine = myEditor.getCaretModel().getLogicalPosition().line;
- for (OnesideDiffChange change : myChangedBlockData.getDiffChanges()) {
+ for (UnifiedDiffChange change : myChangedBlockData.getDiffChanges()) {
if (DiffUtil.isSelectedByLine(caretLine, change.getLine1(), change.getLine2())) return change;
}
return null;
@CalledInAwt
@Nullable
protected OpenFileDescriptor getOpenFileDescriptor(int offset) {
- assert myActualContent1 != null || myActualContent2 != null;
- if (myActualContent2 == null) {
- return myActualContent1.getOpenFileDescriptor(offset);
- }
- if (myActualContent1 == null) {
- return myActualContent2.getOpenFileDescriptor(offset);
- }
-
LogicalPosition position = myEditor.offsetToLogicalPosition(offset);
Pair<int[], Side> pair = transferLineFromOneside(position.line);
- int offset1 = DiffUtil.getOffset(myActualContent1.getDocument(), pair.first[0], position.column);
- int offset2 = DiffUtil.getOffset(myActualContent2.getDocument(), pair.first[1], position.column);
+ int offset1 = DiffUtil.getOffset(getContent1().getDocument(), pair.first[0], position.column);
+ int offset2 = DiffUtil.getOffset(getContent2().getDocument(), pair.first[1], position.column);
// TODO: issue: non-optimal GoToSource position with caret on deleted block for "Compare with local"
// we should transfer using calculated diff, not jump to "somehow related" position from old content's descriptor
- OpenFileDescriptor descriptor1 = myActualContent1.getOpenFileDescriptor(offset1);
- OpenFileDescriptor descriptor2 = myActualContent2.getOpenFileDescriptor(offset2);
+ OpenFileDescriptor descriptor1 = getContent1().getOpenFileDescriptor(offset1);
+ OpenFileDescriptor descriptor2 = getContent2().getOpenFileDescriptor(offset2);
if (descriptor1 == null) return descriptor2;
if (descriptor2 == null) return descriptor1;
return pair.second.select(descriptor1, descriptor2);
// Actions
//
- private class MyPrevNextDifferenceIterable implements PrevNextDifferenceIterable {
+ private class MyPrevNextDifferenceIterable extends PrevNextDifferenceIterableBase<UnifiedDiffChange> {
+ @NotNull
@Override
- public boolean canGoNext() {
- List<OnesideDiffChange> diffChanges = getDiffChanges();
- if (diffChanges == null || diffChanges.isEmpty()) return false;
-
- int line = myEditor.getCaretModel().getLogicalPosition().line;
- OnesideDiffChange lastChange = diffChanges.get(diffChanges.size() - 1);
- if (lastChange.getLine1() <= line) return false;
-
- return true;
+ protected List<UnifiedDiffChange> getChanges() {
+ return ContainerUtil.notNullize(getDiffChanges());
}
+ @NotNull
@Override
- public void goNext() {
- List<OnesideDiffChange> diffChanges = getDiffChanges();
- assert diffChanges != null;
- int line = myEditor.getCaretModel().getLogicalPosition().line;
-
- OnesideDiffChange next = null;
- for (int i = 0; i < diffChanges.size(); i++) {
- OnesideDiffChange change = diffChanges.get(i);
- if (change.getLine1() <= line) continue;
-
- next = change;
- break;
- }
-
- assert next != null;
-
- DiffUtil.scrollEditor(myEditor, next.getLine1(), true);
+ protected EditorEx getEditor() {
+ return myEditor;
}
@Override
- public boolean canGoPrev() {
- List<OnesideDiffChange> diffChanges = getDiffChanges();
- if (diffChanges == null || diffChanges.isEmpty()) return false;
-
- int line = myEditor.getCaretModel().getLogicalPosition().line;
- OnesideDiffChange firstChange = diffChanges.get(0);
- if (firstChange.getLine2() > line) return false;
-
- return true;
+ protected int getStartLine(@NotNull UnifiedDiffChange change) {
+ return change.getLine1();
}
@Override
- public void goPrev() {
- List<OnesideDiffChange> diffChanges = getDiffChanges();
- assert diffChanges != null;
- int line = myEditor.getCaretModel().getLogicalPosition().line;
-
- OnesideDiffChange prev = null;
- for (int i = 0; i < diffChanges.size(); i++) {
- OnesideDiffChange change = diffChanges.get(i);
- if (change.getLine2() <= line) continue;
-
- prev = diffChanges.get(i - 1);
- break;
- }
-
- if (prev == null) prev = diffChanges.get(diffChanges.size() - 1);
+ protected int getEndLine(@NotNull UnifiedDiffChange change) {
+ return change.getLine2();
+ }
- DiffUtil.scrollEditor(myEditor, prev.getLine1(), true);
+ @Override
+ protected void scrollToChange(@NotNull UnifiedDiffChange change) {
+ DiffUtil.scrollEditor(myEditor, change.getLine1(), true);
}
}
}
}
- private class MyToggleExpandByDefaultAction extends ToggleExpandByDefaultAction {
+ private class MyToggleExpandByDefaultAction extends TextDiffViewerUtil.ToggleExpandByDefaultAction {
+ public MyToggleExpandByDefaultAction() {
+ super(getTextSettings());
+ }
+
@Override
protected void expandAll(boolean expand) {
myFoldingModel.expandAll(expand);
}
}
- private class MyHighlightPolicySettingAction extends HighlightPolicySettingAction {
+ private class MyHighlightPolicySettingAction extends TextDiffViewerUtil.HighlightPolicySettingAction {
+ public MyHighlightPolicySettingAction() {
+ super(getTextSettings());
+ }
+
@NotNull
@Override
protected HighlightPolicy getCurrentSetting() {
settings.remove(HighlightPolicy.DO_NOT_HIGHLIGHT);
return settings;
}
+
+ @Override
+ protected void onSettingsChanged() {
+ rediff();
+ }
}
- private class MyIgnorePolicySettingAction extends IgnorePolicySettingAction {
+ private class MyIgnorePolicySettingAction extends TextDiffViewerUtil.IgnorePolicySettingAction {
+ public MyIgnorePolicySettingAction() {
+ super(getTextSettings());
+ }
+
@NotNull
@Override
protected IgnorePolicy getCurrentSetting() {
settings.remove(IgnorePolicy.IGNORE_WHITESPACES_CHUNKS);
return settings;
}
+
+ @Override
+ protected void onSettingsChanged() {
+ rediff();
+ }
}
- private class MyReadOnlyLockAction extends ReadOnlyLockAction {
+ private class MyReadOnlyLockAction extends TextDiffViewerUtil.ReadOnlyLockAction {
public MyReadOnlyLockAction() {
+ super(getContext());
init();
}
protected void doApply(boolean readOnly) {
myReadOnlyLockSet = readOnly;
if (myChangedBlockData != null) {
- for (OnesideDiffChange onesideDiffChange : myChangedBlockData.getDiffChanges()) {
- onesideDiffChange.updateGutterActions();
+ for (UnifiedDiffChange unifiedDiffChange : myChangedBlockData.getDiffChanges()) {
+ unifiedDiffChange.updateGutterActions();
}
}
updateEditorCanBeTyped();
@Override
protected boolean canEdit() {
- return myActualContent1 != null && !myForceReadOnlyFlags[0] && DiffUtil.canMakeWritable(myActualContent1.getDocument()) ||
- myActualContent2 != null && !myForceReadOnlyFlags[1] && DiffUtil.canMakeWritable(myActualContent2.getDocument());
+ return !myForceReadOnlyFlags[0] && DiffUtil.canMakeWritable(getContent1().getDocument()) ||
+ !myForceReadOnlyFlags[1] && DiffUtil.canMakeWritable(getContent2().getDocument());
}
}
private AllLinesIterator(@NotNull Side side) {
mySide = side;
- DocumentContent content = mySide.select(myActualContent1, myActualContent2);
- assert content != null;
- myDocument = content.getDocument();
+ myDocument = getContent(mySide).getDocument();
}
@Override
private class ChangedLinesIterator extends BufferedLineIterator {
@NotNull private final Side mySide;
- @NotNull private final List<OnesideDiffChange> myChanges;
+ @NotNull private final List<UnifiedDiffChange> myChanges;
private int myIndex = 0;
- private ChangedLinesIterator(@NotNull Side side, @NotNull List<OnesideDiffChange> changes) {
+ private ChangedLinesIterator(@NotNull Side side, @NotNull List<UnifiedDiffChange> changes) {
mySide = side;
myChanges = changes;
init();
@Override
public void loadNextBlock() {
- if (myActualContent2 == null) return; // because we want only insertions
LOG.assertTrue(!myStateIsOutOfDate);
- OnesideDiffChange change = myChanges.get(myIndex);
+ UnifiedDiffChange change = myChanges.get(myIndex);
myIndex++;
LineFragment lineFragment = change.getLineFragment();
int insertedStart = lineFragment.getStartOffset2();
int insertedEnd = lineFragment.getEndOffset2();
- CharSequence insertedText = myActualContent2.getDocument().getCharsSequence().subSequence(insertedStart, insertedEnd);
+ CharSequence insertedText = getContent(mySide).getDocument().getCharsSequence().subSequence(insertedStart, insertedEnd);
int lineNumber = lineFragment.getStartLine2();
return myEditor;
}
else if (DiffDataKeys.CURRENT_CHANGE_RANGE.is(dataId)) {
- OnesideDiffChange change = getCurrentChange();
+ UnifiedDiffChange change = getCurrentChange();
if (change != null) {
return new LineRange(change.getLine1(), change.getLine2());
}
}
}
- private static class OnesideDocumentData {
- @NotNull private final CharSequence myText;
- private final int myLines;
-
- @Nullable private final EditorHighlighter myHighlighter;
- @Nullable private final OnesideEditorRangeHighlighter myRangeHighlighter;
-
- public OnesideDocumentData(@NotNull CharSequence text,
- int lines,
- @Nullable EditorHighlighter highlighter,
- @Nullable OnesideEditorRangeHighlighter rangeHighlighter) {
- myText = text;
- myLines = lines;
- myHighlighter = highlighter;
- myRangeHighlighter = rangeHighlighter;
- }
-
- @NotNull
- public CharSequence getText() {
- return myText;
- }
-
- public int getLines() {
- return myLines;
- }
-
- @Nullable
- public EditorHighlighter getHighlighter() {
- return myHighlighter;
- }
-
- @Nullable
- public OnesideEditorRangeHighlighter getRangeHighlighter() {
- return myRangeHighlighter;
- }
- }
-
private static class TwosideDocumentData {
- @NotNull private final OnesideFragmentBuilder myBuilder;
+ @NotNull private final UnifiedFragmentBuilder myBuilder;
@Nullable private final EditorHighlighter myHighlighter;
- @Nullable private final OnesideEditorRangeHighlighter myRangeHighlighter;
+ @Nullable private final UnifiedEditorRangeHighlighter myRangeHighlighter;
- public TwosideDocumentData(@NotNull OnesideFragmentBuilder builder,
+ public TwosideDocumentData(@NotNull UnifiedFragmentBuilder builder,
@Nullable EditorHighlighter highlighter,
- @Nullable OnesideEditorRangeHighlighter rangeHighlighter) {
+ @Nullable UnifiedEditorRangeHighlighter rangeHighlighter) {
myBuilder = builder;
myHighlighter = highlighter;
myRangeHighlighter = rangeHighlighter;
}
@NotNull
- public OnesideFragmentBuilder getBuilder() {
+ public UnifiedFragmentBuilder getBuilder() {
return myBuilder;
}
}
@Nullable
- public OnesideEditorRangeHighlighter getRangeHighlighter() {
+ public UnifiedEditorRangeHighlighter getRangeHighlighter() {
return myRangeHighlighter;
}
}
private static class ChangedBlockData {
- @NotNull private final List<OnesideDiffChange> myDiffChanges;
+ @NotNull private final List<UnifiedDiffChange> myDiffChanges;
@NotNull private final List<RangeMarker> myGuardedRangeBlocks;
@NotNull private final LineNumberConvertor myLineNumberConvertor;
- public ChangedBlockData(@NotNull List<OnesideDiffChange> diffChanges,
+ public ChangedBlockData(@NotNull List<UnifiedDiffChange> diffChanges,
@NotNull List<RangeMarker> guarderRangeBlocks,
@NotNull LineNumberConvertor lineNumberConvertor) {
myDiffChanges = diffChanges;
}
@NotNull
- public List<OnesideDiffChange> getDiffChanges() {
+ public List<UnifiedDiffChange> getDiffChanges() {
return myDiffChanges;
}
private static class CombinedEditorData {
@NotNull private final CharSequence myText;
@Nullable private final EditorHighlighter myHighlighter;
- @Nullable private final OnesideEditorRangeHighlighter myRangeHighlighter;
+ @Nullable private final UnifiedEditorRangeHighlighter myRangeHighlighter;
@Nullable private final FileType myFileType;
@NotNull private final TIntFunction myLineConvertor1;
- @Nullable private final TIntFunction myLineConvertor2;
+ @NotNull private final TIntFunction myLineConvertor2;
public CombinedEditorData(@NotNull CharSequence text,
@Nullable EditorHighlighter highlighter,
- @Nullable OnesideEditorRangeHighlighter rangeHighlighter,
+ @Nullable UnifiedEditorRangeHighlighter rangeHighlighter,
@Nullable FileType fileType,
@NotNull TIntFunction convertor1,
- @Nullable TIntFunction convertor2) {
+ @NotNull TIntFunction convertor2) {
myText = text;
myHighlighter = highlighter;
myRangeHighlighter = rangeHighlighter;
}
@Nullable
- public OnesideEditorRangeHighlighter getRangeHighlighter() {
+ public UnifiedEditorRangeHighlighter getRangeHighlighter() {
return myRangeHighlighter;
}
return myLineConvertor1;
}
- @Nullable
+ @NotNull
public TIntFunction getLineConvertor2() {
return myLineConvertor2;
}
@NotNull
@Override
protected List<? extends Editor> getEditors() {
- return OnesideDiffViewer.this.getEditors();
+ return UnifiedDiffViewer.this.getEditors();
}
@Override
private boolean doScrollToChange(@NotNull ScrollToPolicy scrollToChangePolicy) {
if (myChangedBlockData == null) return false;
- List<OnesideDiffChange> changes = myChangedBlockData.getDiffChanges();
+ List<UnifiedDiffChange> changes = myChangedBlockData.getDiffChanges();
- OnesideDiffChange targetChange = scrollToChangePolicy.select(changes);
+ UnifiedDiffChange targetChange = scrollToChangePolicy.select(changes);
if (targetChange == null) return false;
DiffUtil.scrollEditor(myEditor, targetChange.getLine1(), false);
protected boolean doScrollToContext() {
if (myNavigationContext == null) return false;
if (myChangedBlockData == null) return false;
- if (myActualContent2 == null) return false;
ChangedLinesIterator changedLinesIterator = new ChangedLinesIterator(Side.RIGHT, myChangedBlockData.getDiffChanges());
NavigationContextChecker checker = new NavigationContextChecker(changedLinesIterator, myNavigationContext);
import java.util.Comparator;
import java.util.List;
-public class OnesideEditorHighlighter implements EditorHighlighter {
- public static final Logger LOG = OnesideDiffViewer.LOG;
+class UnifiedEditorHighlighter implements EditorHighlighter {
+ public static final Logger LOG = UnifiedDiffViewer.LOG;
@NotNull private final Document myDocument;
@NotNull private final List<Element> myPieces;
- public OnesideEditorHighlighter(@NotNull Document document,
+ public UnifiedEditorHighlighter(@NotNull Document document,
@NotNull EditorHighlighter highlighter1,
@NotNull EditorHighlighter highlighter2,
@NotNull List<HighlightRange> ranges,
import java.util.ArrayList;
import java.util.List;
-public class OnesideEditorRangeHighlighter {
- public static final Logger LOG = OnesideDiffViewer.LOG;
+class UnifiedEditorRangeHighlighter {
+ public static final Logger LOG = UnifiedDiffViewer.LOG;
@NotNull private final List<Element> myPieces = new ArrayList<Element>();
- public OnesideEditorRangeHighlighter(@Nullable Project project, @NotNull Document document) {
+ public UnifiedEditorRangeHighlighter(@Nullable Project project, @NotNull Document document) {
ApplicationManager.getApplication().assertReadAccessAllowed();
MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, false);
});
}
- public OnesideEditorRangeHighlighter(@Nullable Project project,
+ public UnifiedEditorRangeHighlighter(@Nullable Project project,
@NotNull Document document1,
@NotNull Document document2,
@NotNull List<HighlightRange> ranges) {
*/
package com.intellij.diff.tools.fragmented;
-import com.intellij.diff.fragments.DiffFragment;
import com.intellij.diff.fragments.LineFragment;
import com.intellij.diff.util.LineRange;
import com.intellij.diff.util.Side;
import java.util.List;
// This class works incorrectly with non-fair differences (when chunk of matched lines has different length in left/right files)
-public class OnesideFragmentBuilder {
+class UnifiedFragmentBuilder {
@NotNull private final List<LineFragment> myFragments;
@NotNull private final Document myDocument1;
@NotNull private final Document myDocument2;
@NotNull private final LineNumberConvertor.Builder myConvertor = new LineNumberConvertor.Builder();
@NotNull private final List<LineRange> myChangedLines = new ArrayList<LineRange>();
- public OnesideFragmentBuilder(@NotNull List<LineFragment> fragments,
+ public UnifiedFragmentBuilder(@NotNull List<LineFragment> fragments,
@NotNull Document document1,
@NotNull Document document2,
@NotNull Side masterSide) {
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.holders;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.contents.DiffContent;
+import com.intellij.diff.contents.DocumentContent;
+import com.intellij.diff.contents.FileContent;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorProvider;
+import com.intellij.openapi.fileEditor.TextEditor;
+import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager;
+import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
+import com.intellij.openapi.fileTypes.UIBasedFileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.FocusListener;
+
+public class BinaryEditorHolder extends EditorHolder {
+ @NotNull protected final FileEditor myEditor;
+ @NotNull protected final FileEditorProvider myEditorProvider;
+
+ public BinaryEditorHolder(@NotNull FileEditor editor, @NotNull FileEditorProvider editorProvider) {
+ myEditor = editor;
+ myEditorProvider = editorProvider;
+ }
+
+ @NotNull
+ public FileEditor getEditor() {
+ return myEditor;
+ }
+
+ @Override
+ public void dispose() {
+ myEditorProvider.disposeEditor(myEditor);
+ }
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myEditor.getComponent();
+ }
+
+ @Override
+ public void installFocusListener(@NotNull FocusListener listener) {
+ myEditor.getComponent().addFocusListener(listener);
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return myEditor.getPreferredFocusedComponent();
+ }
+
+ //
+ // Build
+ //
+
+ public static class BinaryEditorHolderFactory extends EditorHolderFactory<BinaryEditorHolder> {
+ public static BinaryEditorHolderFactory INSTANCE = new BinaryEditorHolderFactory();
+
+ @Override
+ @NotNull
+ public BinaryEditorHolder create(@NotNull DiffContent content, @NotNull DiffContext context) {
+ Project project = context.getProject();
+ if (content instanceof FileContent) {
+ if (project == null) project = ProjectManager.getInstance().getDefaultProject();
+ VirtualFile file = ((FileContent)content).getFile();
+
+ FileEditorProvider[] providers = FileEditorProviderManager.getInstance().getProviders(project, file);
+ if (providers.length == 0) throw new IllegalStateException("Can't find FileEditorProvider: " + file.getFileType());
+
+ FileEditorProvider provider = providers[0];
+ FileEditor editor = provider.createEditor(project, file);
+
+ UIUtil.removeScrollBorder(editor.getComponent());
+
+ return new BinaryEditorHolder(editor, provider);
+ }
+ if (content instanceof DocumentContent) {
+ Document document = ((DocumentContent)content).getDocument();
+ final Editor editor = DiffUtil.createEditor(document, project, true);
+
+ TextEditorProvider provider = TextEditorProvider.getInstance();
+ TextEditor fileEditor = provider.getTextEditor(editor);
+
+ Disposer.register(fileEditor, new Disposable() {
+ @Override
+ public void dispose() {
+ EditorFactory.getInstance().releaseEditor(editor);
+ }
+ });
+
+ return new BinaryEditorHolder(fileEditor, provider);
+ }
+
+ throw new IllegalArgumentException(content.getClass() + " - " + content.toString());
+ }
+
+ @Override
+ public boolean canShowContent(@NotNull DiffContent content, @NotNull DiffContext context) {
+ if (content instanceof DocumentContent) return true;
+ if (content instanceof FileContent) {
+ Project project = context.getProject();
+ if (project == null) project = ProjectManager.getInstance().getDefaultProject();
+ VirtualFile file = ((FileContent)content).getFile();
+
+ return FileEditorProviderManager.getInstance().getProviders(project, file).length != 0;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean wantShowContent(@NotNull DiffContent content, @NotNull DiffContext context) {
+ if (content instanceof FileContent) {
+ if (content.getContentType() == null) return false;
+ if (content.getContentType().isBinary()) return true;
+ if (content.getContentType() instanceof UIBasedFileType) return true;
+ return false;
+ }
+ return false;
+ }
+ }
+}
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.diff.tools.util.twoside;
+package com.intellij.diff.tools.holders;
-import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.Disposable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.List;
+import java.awt.event.FocusListener;
-public class TwosideTextContentPanel extends TwosideContentPanel {
- public TwosideTextContentPanel(@NotNull List<JComponent> titleComponents,
- @Nullable Editor editor1,
- @Nullable Editor editor2) {
- super(titleComponents, getComponent(editor1), getComponent(editor2));
- }
+public abstract class EditorHolder implements Disposable {
+ @NotNull
+ public abstract JComponent getComponent();
@Nullable
- private static JComponent getComponent(@Nullable Editor editor) {
- return editor != null ? editor.getComponent() : null;
+ public abstract JComponent getPreferredFocusedComponent();
+
+ public void installFocusListener(@NotNull FocusListener listener) {
}
}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.holders;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.contents.DiffContent;
+import org.jetbrains.annotations.NotNull;
+
+public abstract class EditorHolderFactory<T extends EditorHolder> {
+ public abstract boolean canShowContent(@NotNull DiffContent content, @NotNull DiffContext context);
+
+ public abstract boolean wantShowContent(@NotNull DiffContent content, @NotNull DiffContext context);
+
+ public abstract T create(@NotNull DiffContent content, @NotNull DiffContext context);
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.holders;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.contents.DiffContent;
+import com.intellij.diff.contents.DocumentContent;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.FocusListener;
+
+public class TextEditorHolder extends EditorHolder {
+ @NotNull protected final EditorEx myEditor;
+
+ public TextEditorHolder(@NotNull EditorEx editor) {
+ myEditor = editor;
+ }
+
+ @NotNull
+ public EditorEx getEditor() {
+ return myEditor;
+ }
+
+ @Override
+ public void dispose() {
+ EditorFactory.getInstance().releaseEditor(myEditor);
+ }
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myEditor.getComponent();
+ }
+
+ @Override
+ public void installFocusListener(@NotNull FocusListener listener) {
+ myEditor.getContentComponent().addFocusListener(listener);
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return myEditor.getContentComponent();
+ }
+
+ //
+ // Build
+ //
+
+ public static class TextEditorHolderFactory extends EditorHolderFactory<TextEditorHolder> {
+ public static TextEditorHolderFactory INSTANCE = new TextEditorHolderFactory();
+
+ @Override
+ @NotNull
+ public TextEditorHolder create(@NotNull DiffContent content, @NotNull DiffContext context) {
+ if (!(content instanceof DocumentContent)) throw new IllegalArgumentException(content.toString());
+ Project project = context.getProject();
+ DocumentContent documentContent = (DocumentContent)content;
+
+ EditorEx editor = DiffUtil.createEditor(documentContent.getDocument(), project, false, true);
+ DiffUtil.configureEditor(editor, documentContent, project);
+ return new TextEditorHolder(editor);
+ }
+
+ @Override
+ public boolean canShowContent(@NotNull DiffContent content, @NotNull DiffContext context) {
+ if (content instanceof DocumentContent) return true;
+ return false;
+ }
+
+ @Override
+ public boolean wantShowContent(@NotNull DiffContent content, @NotNull DiffContext context) {
+ if (content instanceof DocumentContent) return true;
+ return false;
+ }
+ }
+}
@NotNull private final LineFragment myFragment;
@Nullable private final List<DiffFragment> myInnerFragments;
- @Nullable private final EditorEx myEditor1;
- @Nullable private final EditorEx myEditor2;
-
@NotNull private final List<RangeHighlighter> myHighlighters = new ArrayList<RangeHighlighter>();
@NotNull private final List<MyGutterOperation> myOperations = new ArrayList<MyGutterOperation>();
// TODO: adjust color from inner fragments - configurable
public SimpleDiffChange(@NotNull SimpleDiffViewer viewer,
@NotNull LineFragment fragment,
- @Nullable EditorEx editor1,
- @Nullable EditorEx editor2,
boolean inlineHighlight) {
myViewer = viewer;
myFragment = fragment;
myInnerFragments = inlineHighlight ? fragment.getInnerFragments() : null;
- myEditor1 = editor1;
- myEditor2 = editor2;
-
installHighlighter();
}
}
private void doInstallActionHighlighters() {
- if (myEditor1 != null && myEditor2 != null) {
- myOperations.add(createOperation(Side.LEFT));
- myOperations.add(createOperation(Side.RIGHT));
- }
+ myOperations.add(createOperation(Side.LEFT));
+ myOperations.add(createOperation(Side.RIGHT));
}
private void createHighlighter(@NotNull Side side, boolean ignored) {
- Editor editor = side.select(myEditor1, myEditor2);
- if (editor == null) return;
+ Editor editor = myViewer.getEditor(side);
int start = side.getStartOffset(myFragment);
int end = side.getEndOffset(myFragment);
}
private void createInlineHighlighter(@NotNull DiffFragment fragment, @NotNull Side side) {
- Editor editor = side.select(myEditor1, myEditor2);
- if (editor == null) return;
-
int start = side.getStartOffset(fragment);
int end = side.getEndOffset(fragment);
TextDiffType type = DiffUtil.getDiffType(fragment);
start += startOffset;
end += startOffset;
+ Editor editor = myViewer.getEditor(side);
RangeHighlighter highlighter = DiffDrawUtil.createInlineHighlighter(editor, start, end, type);
myHighlighters.add(highlighter);
}
public boolean processChange(int oldLine1, int oldLine2, int shift, @NotNull Side side) {
int line1 = getStartLine(side);
int line2 = getEndLine(side);
+ int sideIndex = side.getIndex();
- if (line2 <= oldLine1) return false;
- if (line1 >= oldLine2) {
- myLineStartShifts[side.getIndex()] += shift;
- myLineEndShifts[side.getIndex()] += shift;
- return false;
- }
+ DiffUtil.UpdatedLineRange newRange = DiffUtil.updateRangeOnModification(line1, line2, oldLine1, oldLine2, shift);
+ myLineStartShifts[sideIndex] += newRange.startLine - line1;
+ myLineEndShifts[sideIndex] += newRange.endLine - line2;
- if (line1 <= oldLine1 && line2 >= oldLine2) {
- myLineEndShifts[side.getIndex()] += shift;
- return false;
- }
+ if (newRange.damaged) {
+ for (MyGutterOperation operation : myOperations) {
+ operation.dispose();
+ }
+ myOperations.clear();
- for (MyGutterOperation operation : myOperations) {
- operation.dispose();
+ myIsValid = false;
}
- myOperations.clear();
- myIsValid = false;
- return true;
+ return newRange.damaged;
}
//
//
public boolean isSelectedByLine(int line, @NotNull Side side) {
- if (myEditor1 == null || myEditor2 == null) return false;
-
int line1 = getStartLine(side);
int line2 = getEndLine(side);
@NotNull
private MyGutterOperation createOperation(@NotNull Side side) {
- assert myEditor1 != null && myEditor2 != null;
int offset = side.getStartOffset(myFragment);
- EditorEx editor = side.select(myEditor1, myEditor2);
+ EditorEx editor = myViewer.getEditor(side);
RangeHighlighter highlighter = editor.getMarkupModel().addRangeHighlighter(offset, offset,
HighlighterLayer.ADDITIONAL_SYNTAX,
null,
@Nullable
public GutterIconRenderer createRenderer() {
- assert myEditor1 != null && myEditor2 != null;
-
myCtrlPressed = myViewer.getModifierProvider().isCtrlPressed();
myShiftPressed = myViewer.getModifierProvider().isShiftPressed();
- boolean isEditable = DiffUtil.isEditable(mySide.select(myEditor1, myEditor2));
- boolean isOtherEditable = DiffUtil.isEditable(mySide.other().select(myEditor1, myEditor2));
+ boolean isEditable = DiffUtil.isEditable(myViewer.getEditor(mySide));
+ boolean isOtherEditable = DiffUtil.isEditable(myViewer.getEditor(mySide.other()));
boolean isAppendable = myFragment.getStartLine1() != myFragment.getEndLine1() &&
myFragment.getStartLine2() != myFragment.getEndLine2();
@NotNull final String tooltipText,
@NotNull final Icon icon,
@NotNull final Runnable perform) {
- assert myEditor1 != null && myEditor2 != null;
- if (!DiffUtil.isEditable(sourceSide.other().select(myEditor1, myEditor2))) return null;
+ if (!DiffUtil.isEditable(myViewer.getEditor(sourceSide.other()))) return null;
return new GutterIconRenderer() {
@NotNull
@Override
return new DumbAwareAction() {
@Override
public void actionPerformed(AnActionEvent e) {
- final Project project = e.getProject();
- final Document document1 = myEditor1.getDocument();
- final Document document2 = myEditor2.getDocument();
-
if (!myIsValid) return;
-
- DiffUtil.executeWriteCommand(sourceSide.other().select(document1, document2), project, "Replace change", new Runnable() {
+ final Project project = e.getProject();
+ final Document document = myViewer.getEditor(sourceSide.other()).getDocument();
+ DiffUtil.executeWriteCommand(document, project, "Replace change", new Runnable() {
@Override
public void run() {
perform.run();
@NotNull
@Override
public DiffViewer createComponent(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ if (SimpleOnesideDiffViewer.canShowRequest(context, request)) return new SimpleOnesideDiffViewer(context, request);
+ if (SimpleDiffViewer.canShowRequest(context, request)) return new SimpleDiffViewer(context, request);
if (SimpleThreesideDiffViewer.canShowRequest(context, request)) return new SimpleThreesideDiffViewer(context, request);
- return new SimpleDiffViewer(context, request);
+ throw new IllegalArgumentException(request.toString());
}
@Override
public boolean canShow(@NotNull DiffContext context, @NotNull DiffRequest request) {
- return SimpleDiffViewer.canShowRequest(context, request) || SimpleThreesideDiffViewer.canShowRequest(context, request);
+ return SimpleOnesideDiffViewer.canShowRequest(context, request) ||
+ SimpleDiffViewer.canShowRequest(context, request) ||
+ SimpleThreesideDiffViewer.canShowRequest(context, request);
}
@NotNull
import com.intellij.diff.actions.BufferedLineIterator;
import com.intellij.diff.actions.NavigationContextChecker;
import com.intellij.diff.comparison.DiffTooBigException;
-import com.intellij.diff.contents.DocumentContent;
import com.intellij.diff.fragments.LineFragment;
-import com.intellij.diff.fragments.LineFragmentImpl;
import com.intellij.diff.requests.ContentDiffRequest;
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.tools.util.base.TextDiffViewerUtil;
+import com.intellij.diff.tools.util.side.TwosideTextDiffViewer;
import com.intellij.diff.util.*;
import com.intellij.diff.util.DiffUserDataKeysEx.ScrollToPolicy;
import com.intellij.diff.util.DiffUtil.DocumentData;
import com.intellij.icons.AllIcons;
-import com.intellij.ide.IdeEventQueue;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
-import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.*;
import javax.swing.*;
import java.awt.*;
-import java.awt.event.KeyEvent;
-import java.awt.event.WindowEvent;
-import java.awt.event.WindowFocusListener;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Iterator;
import java.util.List;
import static com.intellij.diff.util.DiffUtil.getLineCount;
@NotNull private final List<SimpleDiffChange> myDiffChanges = new ArrayList<SimpleDiffChange>();
@NotNull private final List<SimpleDiffChange> myInvalidDiffChanges = new ArrayList<SimpleDiffChange>();
- @Nullable private final MyFoldingModel myFoldingModel;
+ @NotNull private final MyFoldingModel myFoldingModel;
@NotNull private final MyInitialScrollHelper myInitialScrollHelper = new MyInitialScrollHelper();
@NotNull private final ModifierProvider myModifierProvider;
mySyncScrollable = new MySyncScrollable();
myPrevNextDifferenceIterable = new MyPrevNextDifferenceIterable();
myStatusPanel = new MyStatusPanel();
- myFoldingModel = createFoldingModel(getEditor1(), getEditor2());
+ myFoldingModel = new MyFoldingModel(getEditors(), this);
myModifierProvider = new ModifierProvider();
}
@Override
@CalledInAwt
protected void onDispose() {
- myModifierProvider.destroy();
destroyChangedBlocks();
super.onDispose();
}
protected List<AnAction> createToolbarActions() {
List<AnAction> group = new ArrayList<AnAction>();
- group.add(new IgnorePolicySettingAction());
- group.add(new HighlightPolicySettingAction());
+ group.add(new MyIgnorePolicySettingAction());
+ group.add(new MyHighlightPolicySettingAction());
group.add(new MyToggleExpandByDefaultAction());
- group.add(new ToggleAutoScrollAction());
+ group.add(new MyToggleAutoScrollAction());
group.add(new MyReadOnlyLockAction());
group.add(myEditorSettingsAction);
List<AnAction> group = new ArrayList<AnAction>();
group.add(Separator.getInstance());
- group.add(new IgnorePolicySettingAction().getPopupGroup());
+ group.add(new MyIgnorePolicySettingAction().getPopupGroup());
group.add(Separator.getInstance());
- group.add(new HighlightPolicySettingAction().getPopupGroup());
+ group.add(new MyHighlightPolicySettingAction().getPopupGroup());
group.add(Separator.getInstance());
- group.add(new ToggleAutoScrollAction());
+ group.add(new MyToggleAutoScrollAction());
group.add(new MyToggleExpandByDefaultAction());
return group;
return group;
}
- @Nullable
- private MyFoldingModel createFoldingModel(@Nullable EditorEx editor1, @Nullable EditorEx editor2) {
- if (editor1 == null || editor2 == null) return null;
-
- return new MyFoldingModel(editor1, editor2, this);
- }
-
@Override
@CalledInAwt
protected void processContextHints() {
@CalledInAwt
protected void updateContextHints() {
super.updateContextHints();
- if (myFoldingModel != null) myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
+ myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
myInitialScrollHelper.updateContext(myRequest);
}
// Diff
//
+ @NotNull
+ public FoldingModelSupport.Settings getFoldingModelSettings() {
+ return TextDiffViewerUtil.getFoldingModelSettings(myContext);
+ }
+
@Override
protected void onSlowRediff() {
super.onSlowRediff();
try {
indicator.checkCanceled();
- assert getActualContent1() != null || getActualContent2() != null;
-
- if (getActualContent1() == null) {
- final DocumentContent content = getActualContent2();
- final Document document = content.getDocument();
-
- CompareData data = ApplicationManager.getApplication().runReadAction(new Computable<CompareData>() {
- @Override
- public CompareData compute() {
- List<LineFragment> fragments = Collections.<LineFragment>singletonList(new LineFragmentImpl(0, 0, 0, getLineCount(document),
- 0, 0, 0, document.getTextLength()));
- return new CompareData(fragments, false);
- }
- });
-
- return apply(data);
- }
-
- if (getActualContent2() == null) {
- final DocumentContent content = getActualContent1();
- final Document document = content.getDocument();
-
- CompareData data = ApplicationManager.getApplication().runReadAction(new Computable<CompareData>() {
- @Override
- public CompareData compute() {
- List<LineFragment> fragments = Collections.<LineFragment>singletonList(new LineFragmentImpl(0, getLineCount(document), 0, 0,
- 0, document.getTextLength(), 0, 0));
- return new CompareData(fragments, false);
- }
- });
-
- return apply(data);
- }
-
- final DocumentContent content1 = getActualContent1();
- final DocumentContent content2 = getActualContent2();
- final Document document1 = content1.getDocument();
- final Document document2 = content2.getDocument();
+ final Document document1 = getContent1().getDocument();
+ final Document document2 = getContent2().getDocument();
DocumentData data = ApplicationManager.getApplication().runReadAction(new Computable<DocumentData>() {
@Override
return apply(new CompareData(lineFragments, isEqualContents));
}
- catch (DiffTooBigException ignore) {
+ catch (DiffTooBigException e) {
return applyNotification(DiffNotifications.DIFF_TOO_BIG);
}
- catch (ProcessCanceledException ignore) {
- return applyNotification(DiffNotifications.OPERATION_CANCELED);
+ catch (ProcessCanceledException e) {
+ throw e;
}
catch (Throwable e) {
LOG.error(e);
return new Runnable() {
@Override
public void run() {
- if (myFoldingModel != null) myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
+ myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
clearDiffPresentation();
if (data.isEqualContent()) myPanel.addNotification(DiffNotifications.EQUAL_CONTENTS);
if (data.getFragments() != null) {
for (LineFragment fragment : data.getFragments()) {
- myDiffChanges.add(new SimpleDiffChange(SimpleDiffViewer.this, fragment, getEditor1(), getEditor2(),
- getHighlightPolicy().isFineFragments()));
+ myDiffChanges.add(new SimpleDiffChange(SimpleDiffViewer.this, fragment, getHighlightPolicy().isFineFragments()));
}
}
- if (myFoldingModel != null) {
- myFoldingModel.install(data.getFragments(), myRequest, getFoldingModelSettings());
- }
+ myFoldingModel.install(data.getFragments(), myRequest, getFoldingModelSettings());
myInitialScrollHelper.onRediff();
}
myInvalidDiffChanges.clear();
- if (myFoldingModel != null) myFoldingModel.destroy();
+ myFoldingModel.destroy();
myContentPanel.repaintDivider();
myStatusPanel.update();
protected void onBeforeDocumentChange(@NotNull DocumentEvent e) {
super.onBeforeDocumentChange(e);
if (myDiffChanges.isEmpty()) return;
- if (getEditor1() == null || getEditor2() == null) return;
Side side = null;
if (e.getDocument() == getEditor(Side.LEFT).getDocument()) side = Side.LEFT;
return;
}
- int offset1 = e.getOffset();
- int offset2 = e.getOffset() + e.getOldLength();
-
- if (StringUtil.endsWithChar(e.getOldFragment(), '\n') &&
- StringUtil.endsWithChar(e.getNewFragment(), '\n')) {
- offset2--;
- }
-
- int line1 = e.getDocument().getLineNumber(offset1);
- int line2 = e.getDocument().getLineNumber(offset2) + 1;
- int shift = StringUtil.countNewLines(e.getNewFragment()) - StringUtil.countNewLines(e.getOldFragment());
+ int line1 = e.getDocument().getLineNumber(e.getOffset());
+ int line2 = e.getDocument().getLineNumber(e.getOffset() + e.getOldLength()) + 1;
+ int shift = DiffUtil.countLinesShift(e);
List<SimpleDiffChange> invalid = new ArrayList<SimpleDiffChange>();
for (SimpleDiffChange change : myDiffChanges) {
@Override
protected void onDocumentChange(@NotNull DocumentEvent e) {
super.onDocumentChange(e);
- if (myFoldingModel != null) myFoldingModel.onDocumentChanged(e);
+ myFoldingModel.onDocumentChanged(e);
}
@CalledInAwt
protected boolean doScrollToChange(@NotNull ScrollToPolicy scrollToPolicy) {
- if (getEditor1() == null || getEditor2() == null) return true;
-
SimpleDiffChange targetChange = scrollToPolicy.select(myDiffChanges);
if (targetChange == null) return false;
}
private void doScrollToChange(@NotNull SimpleDiffChange change, final boolean animated) {
- if (getEditor1() == null || getEditor2() == null) return;
- assert mySyncScrollSupport != null;
-
final int line1 = change.getStartLine(Side.LEFT);
final int line2 = change.getStartLine(Side.RIGHT);
final int endLine1 = change.getEndLine(Side.LEFT);
DiffUtil.moveCaret(getEditor1(), line1);
DiffUtil.moveCaret(getEditor2(), line2);
- mySyncScrollSupport.makeVisible(getCurrentSide(), line1, endLine1, line2, endLine2, animated);
+ getSyncScrollSupport().makeVisible(getCurrentSide(), line1, endLine1, line2, endLine2, animated);
}
protected boolean doScrollToContext(@NotNull DiffNavigationContext context) {
- if (getEditor2() == null) return false;
-
ChangedLinesIterator changedLinesIterator = new ChangedLinesIterator(Side.RIGHT);
NavigationContextChecker checker = new NavigationContextChecker(changedLinesIterator, context);
int line = checker.contextMatchCheck();
return myModifierProvider;
}
+ @NotNull
+ @Override
+ public SyncScrollSupport.TwosideSyncScrollSupport getSyncScrollSupport() {
+ //noinspection ConstantConditions
+ return super.getSyncScrollSupport();
+ }
+
//
// Misc
//
@NotNull
@CalledInAwt
private List<SimpleDiffChange> getSelectedChanges(@NotNull Side side) {
- EditorEx editor = getEditor(side);
- if (editor == null) return Collections.emptyList();
+ final BitSet lines = DiffUtil.getSelectedLines(getEditor(side));
- final BitSet lines = DiffUtil.getSelectedLines(editor);
List<SimpleDiffChange> affectedChanges = new ArrayList<SimpleDiffChange>();
for (int i = myDiffChanges.size() - 1; i >= 0; i--) {
SimpleDiffChange change = myDiffChanges.get(i);
@Nullable
@CalledInAwt
private SimpleDiffChange getSelectedChange(@NotNull Side side) {
- EditorEx editor = getEditor(side);
- if (editor == null) return null;
-
- int caretLine = editor.getCaretModel().getLogicalPosition().line;
+ int caretLine = getEditor(side).getCaretModel().getLogicalPosition().line;
for (SimpleDiffChange change : myDiffChanges) {
int line1 = change.getStartLine(side);
// Actions
//
- private class MyPrevNextDifferenceIterable implements PrevNextDifferenceIterable {
+ private class MyPrevNextDifferenceIterable extends PrevNextDifferenceIterableBase<SimpleDiffChange> {
+ @NotNull
@Override
- public boolean canGoNext() {
- if (myDiffChanges.isEmpty()) return false;
-
- EditorEx editor = getCurrentEditor();
- int line = editor.getCaretModel().getLogicalPosition().line;
- if (line == editor.getDocument().getLineCount() - 1) return false;
-
- SimpleDiffChange lastChange = myDiffChanges.get(myDiffChanges.size() - 1);
- if (lastChange.getStartLine(getCurrentSide()) <= line) return false;
-
- return true;
+ protected List<SimpleDiffChange> getChanges() {
+ return myDiffChanges;
}
+ @NotNull
@Override
- public void goNext() {
- EditorEx editor = getCurrentEditor();
-
- int line = editor.getCaretModel().getLogicalPosition().line;
-
- SimpleDiffChange next = null;
- for (int i = 0; i < myDiffChanges.size(); i++) {
- SimpleDiffChange change = myDiffChanges.get(i);
- if (change.getStartLine(getCurrentSide()) <= line) continue;
-
- next = change;
- break;
- }
-
- assert next != null;
- doScrollToChange(next, true);
+ protected EditorEx getEditor() {
+ return getCurrentEditor();
}
@Override
- public boolean canGoPrev() {
- if (myDiffChanges.isEmpty()) return false;
-
- EditorEx editor = getCurrentEditor();
- int line = editor.getCaretModel().getLogicalPosition().line;
- if (line == 0) return false;
-
- SimpleDiffChange firstChange = myDiffChanges.get(0);
- if (firstChange.getEndLine(getCurrentSide()) > line) return false;
- if (firstChange.getStartLine(getCurrentSide()) >= line) return false;
-
- return true;
+ protected int getStartLine(@NotNull SimpleDiffChange change) {
+ return change.getStartLine(getCurrentSide());
}
@Override
- public void goPrev() {
- EditorEx editor = getCurrentEditor();
-
- int line = editor.getCaretModel().getLogicalPosition().line;
-
- SimpleDiffChange prev = null;
- for (int i = 0; i < myDiffChanges.size(); i++) {
- SimpleDiffChange change = myDiffChanges.get(i);
-
- SimpleDiffChange next = i < myDiffChanges.size() - 1 ? myDiffChanges.get(i + 1) : null;
- if (next == null || next.getEndLine(getCurrentSide()) > line || next.getStartLine(getCurrentSide()) >= line) {
- prev = change;
- break;
- }
- }
+ protected int getEndLine(@NotNull SimpleDiffChange change) {
+ return change.getEndLine(getCurrentSide());
+ }
- assert prev != null;
- doScrollToChange(prev, true);
+ @Override
+ protected void scrollToChange(@NotNull SimpleDiffChange change) {
+ doScrollToChange(change, true);
}
}
- private class MyReadOnlyLockAction extends EditorReadOnlyLockAction {
+ private class MyReadOnlyLockAction extends TextDiffViewerUtil.EditorReadOnlyLockAction {
+ public MyReadOnlyLockAction() {
+ super(getContext(), getEditableEditors());
+ }
+
@Override
protected void doApply(boolean readOnly) {
super.doApply(readOnly);
@Override
public void update(@NotNull AnActionEvent e) {
Editor editor = e.getData(CommonDataKeys.EDITOR);
- Side side = Side.fromLeft(editor == getEditor1());
-
- if (getEditor1() == null || getEditor2() == null) {
- e.getPresentation().setEnabledAndVisible(false);
- return;
- }
-
if (editor != getEditor1() && editor != getEditor2()) {
e.getPresentation().setEnabledAndVisible(false);
return;
}
- Editor modifiedEditor = side.other(myModifyOpposite).select(getEditor1(), getEditor2());
+ Side side = Side.fromLeft(editor == getEditor(Side.LEFT));
+ Editor modifiedEditor = getEditor(side.other(myModifyOpposite));
+
if (!DiffUtil.isEditable(modifiedEditor)) {
e.getPresentation().setEnabledAndVisible(false);
return;
}
e.getPresentation().setIcon(getIcon(side));
+ e.getPresentation().setVisible(true);
e.getPresentation().setEnabled(isSomeChangeSelected(side));
}
@Override
public void actionPerformed(@NotNull final AnActionEvent e) {
- assert getEditor1() != null && getEditor2() != null;
-
Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
- final Side side = Side.fromLeft(editor == getEditor1());
+ final Side side = Side.fromLeft(editor == getEditor(Side.LEFT));
final List<SimpleDiffChange> selectedChanges = getSelectedChanges(side);
- Editor modifiedEditor = side.other(myModifyOpposite).select(getEditor1(), getEditor2());
+ Editor modifiedEditor = getEditor(side.other(myModifyOpposite));
String title = e.getPresentation().getText() + " selected changes";
DiffUtil.executeWriteCommand(modifiedEditor.getDocument(), e.getProject(), title, new Runnable() {
@Override
protected boolean isSomeChangeSelected(@NotNull Side side) {
if (myDiffChanges.isEmpty()) return false;
- Editor editor = getEditor(side);
- if (editor == null) return false;
-
- List<Caret> carets = editor.getCaretModel().getAllCarets();
+ List<Caret> carets = getEditor(side).getCaretModel().getAllCarets();
if (carets.size() != 1) return true;
Caret caret = carets.get(0);
if (caret.hasSelection()) return true;
@CalledWithWriteLock
public void replaceChange(@NotNull SimpleDiffChange change, @NotNull final Side sourceSide) {
- assert getEditor1() != null && getEditor2() != null;
-
if (!change.isValid()) return;
+ Side outputSide = sourceSide.other();
- final Document document1 = getEditor1().getDocument();
- final Document document2 = getEditor2().getDocument();
-
- DiffUtil.applyModification(sourceSide.other().select(document1, document2),
- change.getStartLine(sourceSide.other()), change.getEndLine(sourceSide.other()),
- sourceSide.select(document1, document2),
- change.getStartLine(sourceSide), change.getEndLine(sourceSide));
+ DiffUtil.applyModification(getEditor(outputSide).getDocument(), change.getStartLine(outputSide), change.getEndLine(outputSide),
+ getEditor(sourceSide).getDocument(), change.getStartLine(sourceSide), change.getEndLine(sourceSide));
change.destroyHighlighter();
myDiffChanges.remove(change);
@CalledWithWriteLock
public void appendChange(@NotNull SimpleDiffChange change, @NotNull final Side sourceSide) {
- assert getEditor1() != null && getEditor2() != null;
-
if (!change.isValid()) return;
if (change.getStartLine(sourceSide) == change.getEndLine(sourceSide)) return;
+ Side outputSide = sourceSide.other();
- final Document document1 = getEditor1().getDocument();
- final Document document2 = getEditor2().getDocument();
-
- DiffUtil.applyModification(sourceSide.other().select(document1, document2),
- change.getEndLine(sourceSide.other()), change.getEndLine(sourceSide.other()),
- sourceSide.select(document1, document2),
- change.getStartLine(sourceSide), change.getEndLine(sourceSide));
+ DiffUtil.applyModification(getEditor(outputSide).getDocument(), change.getEndLine(outputSide), change.getEndLine(outputSide),
+ getEditor(sourceSide).getDocument(), change.getStartLine(sourceSide), change.getEndLine(sourceSide));
change.destroyHighlighter();
myDiffChanges.remove(change);
}
- private class MyToggleExpandByDefaultAction extends ToggleExpandByDefaultAction {
+ private class MyHighlightPolicySettingAction extends TextDiffViewerUtil.HighlightPolicySettingAction {
+ public MyHighlightPolicySettingAction() {
+ super(getTextSettings());
+ }
+
+ @Override
+ protected void onSettingsChanged() {
+ rediff();
+ }
+ }
+
+ private class MyIgnorePolicySettingAction extends TextDiffViewerUtil.IgnorePolicySettingAction {
+ public MyIgnorePolicySettingAction() {
+ super(getTextSettings());
+ }
+
+ @Override
+ protected void onSettingsChanged() {
+ rediff();
+ }
+ }
+
+ private class MyToggleExpandByDefaultAction extends TextDiffViewerUtil.ToggleExpandByDefaultAction {
+ public MyToggleExpandByDefaultAction() {
+ super(getTextSettings());
+ }
+
@Override
protected void expandAll(boolean expand) {
- if (myFoldingModel != null) myFoldingModel.expandAll(expand);
+ myFoldingModel.expandAll(expand);
}
}
private AllLinesIterator(@NotNull Side side) {
mySide = side;
- Editor editor = getEditor(mySide);
- assert editor != null;
- myDocument = editor.getDocument();
+ myDocument = getEditor(mySide).getDocument();
}
@Override
int line1 = change.getStartLine(mySide);
int line2 = change.getEndLine(mySide);
- Editor editor = getEditor(mySide);
- assert editor != null;
- Document document = editor.getDocument();
+ Document document = getEditor(mySide).getDocument();
for (int i = line1; i < line2; i++) {
int offset1 = document.getLineStartOffset(i);
@Override
protected void processHelper(@NotNull ScrollHelper helper) {
- assert getEditor1() != null && getEditor2() != null;
-
if (!helper.process(0, 0)) return;
for (SimpleDiffChange diffChange : myDiffChanges) {
if (!helper.process(diffChange.getStartLine(Side.LEFT), diffChange.getStartLine(Side.RIGHT))) return;
private class MyDividerPainter implements DiffSplitter.Painter, DiffDividerDrawUtil.DividerPaintable {
@Override
public void paint(@NotNull Graphics g, @NotNull JComponent divider) {
- if (getEditor1() == null || getEditor2() == null) return;
Graphics2D gg = DiffDividerDrawUtil.getDividerGraphics(g, divider, getEditor1().getComponent());
gg.setColor(DiffDrawUtil.getDividerColor(getEditor1()));
//DividerPolygonUtil.paintSimplePolygons(gg, divider.getWidth(), getEditor1(), getEditor2(), this);
DiffDividerDrawUtil.paintPolygons(gg, divider.getWidth(), getEditor1(), getEditor2(), this);
- if (myFoldingModel != null) myFoldingModel.paintOnDivider(gg, divider);
+ myFoldingModel.paintOnDivider(gg, divider);
gg.dispose();
}
}
}
- public class ModifierProvider {
- private boolean myShiftPressed;
- private boolean myCtrlPressed;
- private boolean myAltPressed;
-
- private Window myWindow;
-
- private final WindowFocusListener myWindowFocusListener = new WindowFocusListener() {
- @Override
- public void windowGainedFocus(WindowEvent e) {
- resetState();
- }
-
- @Override
- public void windowLostFocus(WindowEvent e) {
- resetState();
- }
- };
-
+ public class ModifierProvider extends KeyboardModifierListener {
public void init() {
- // we can use KeyListener on Editors, but Ctrl+Click will not work with focus in other place.
- // ex: commit dialog with focus in commit message
- IdeEventQueue.getInstance().addPostprocessor(new IdeEventQueue.EventDispatcher() {
- @Override
- public boolean dispatch(AWTEvent e) {
- if (e instanceof KeyEvent) {
- onKeyEvent((KeyEvent)e);
- }
- return false;
- }
- }, SimpleDiffViewer.this);
-
- myWindow = UIUtil.getWindow(myPanel);
- if (myWindow != null) {
- myWindow.addWindowFocusListener(myWindowFocusListener);
- }
- }
-
- public void destroy() {
- if (myWindow != null) {
- myWindow.removeWindowFocusListener(myWindowFocusListener);
- }
+ init(myPanel, SimpleDiffViewer.this);
}
- private void onKeyEvent(KeyEvent e) {
- final int keyCode = e.getKeyCode();
- if (keyCode == KeyEvent.VK_SHIFT) {
- myShiftPressed = e.getID() == KeyEvent.KEY_PRESSED;
- updateActions();
- }
- if (keyCode == KeyEvent.VK_CONTROL) {
- myCtrlPressed = e.getID() == KeyEvent.KEY_PRESSED;
- updateActions();
- }
- if (keyCode == KeyEvent.VK_ALT) {
- myAltPressed = e.getID() == KeyEvent.KEY_PRESSED;
- updateActions();
- }
- }
-
- private void resetState() {
- myShiftPressed = false;
- myAltPressed = false;
- myCtrlPressed = false;
- updateActions();
- }
-
- public boolean isShiftPressed() {
- return myShiftPressed;
- }
-
- public boolean isCtrlPressed() {
- return myCtrlPressed;
- }
-
- public boolean isAltPressed() {
- return myAltPressed;
- }
-
- public void updateActions() {
+ @Override
+ public void onModifiersChanged() {
for (SimpleDiffChange change : myDiffChanges) {
change.updateGutterActions(false);
}
private static class MyFoldingModel extends FoldingModelSupport {
private final MyPaintable myPaintable = new MyPaintable(0, 1);
- public MyFoldingModel(@NotNull EditorEx editor1, @NotNull EditorEx editor2, @NotNull Disposable disposable) {
- super(new EditorEx[]{editor1, editor2}, disposable);
+ public MyFoldingModel(@NotNull List<? extends EditorEx> editors, @NotNull Disposable disposable) {
+ super(editors.toArray(new EditorEx[2]), disposable);
}
public void install(@Nullable final List<LineFragment> fragments,
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.simple;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.actions.NavigationContextChecker;
+import com.intellij.diff.contents.DocumentContent;
+import com.intellij.diff.requests.ContentDiffRequest;
+import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.util.DiffDataKeys;
+import com.intellij.diff.tools.util.base.HighlightPolicy;
+import com.intellij.diff.tools.util.base.TextDiffViewerUtil;
+import com.intellij.diff.tools.util.side.OnesideTextDiffViewer;
+import com.intellij.diff.util.DiffDrawUtil;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.diff.util.LineRange;
+import com.intellij.diff.util.TextDiffType;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.Separator;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.DiffNavigationContext;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.markup.RangeHighlighter;
+import com.intellij.openapi.editor.markup.SeparatorPlacement;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.util.Pair;
+import org.jetbrains.annotations.CalledInAwt;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import static com.intellij.diff.util.DiffUtil.getLineCount;
+
+public class SimpleOnesideDiffViewer extends OnesideTextDiffViewer {
+ public static final Logger LOG = Logger.getInstance(SimpleOnesideDiffViewer.class);
+
+ @NotNull private final MyInitialScrollHelper myInitialScrollHelper = new MyInitialScrollHelper();
+
+ @NotNull private final List<RangeHighlighter> myHighlighters = new ArrayList<RangeHighlighter>();
+
+ public SimpleOnesideDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ super(context, (ContentDiffRequest)request);
+ }
+
+ @Override
+ @CalledInAwt
+ protected void onDispose() {
+ for (RangeHighlighter highlighter : myHighlighters) {
+ highlighter.dispose();
+ }
+ myHighlighters.clear();
+ super.onDispose();
+ }
+
+ @NotNull
+ @Override
+ protected List<AnAction> createToolbarActions() {
+ List<AnAction> group = new ArrayList<AnAction>();
+
+ group.add(new MyIgnorePolicySettingAction());
+ group.add(new MyHighlightPolicySettingAction());
+ group.add(new MyReadOnlyLockAction());
+ group.add(myEditorSettingsAction);
+
+ return group;
+ }
+
+ @Nullable
+ @Override
+ protected List<AnAction> createPopupActions() {
+ List<AnAction> group = new ArrayList<AnAction>();
+
+ group.add(Separator.getInstance());
+ group.add(new MyIgnorePolicySettingAction().getPopupGroup());
+ group.add(Separator.getInstance());
+ group.add(new MyHighlightPolicySettingAction().getPopupGroup());
+
+ return group;
+ }
+
+ @Override
+ @CalledInAwt
+ protected void processContextHints() {
+ super.processContextHints();
+ myInitialScrollHelper.processContext(myRequest);
+ }
+
+ @Override
+ @CalledInAwt
+ protected void updateContextHints() {
+ super.updateContextHints();
+ myInitialScrollHelper.updateContext(myRequest);
+ }
+
+ //
+ // Diff
+ //
+
+ @Override
+ @NotNull
+ protected Runnable performRediff(@NotNull final ProgressIndicator indicator) {
+ indicator.checkCanceled();
+
+ return new Runnable() {
+ @Override
+ public void run() {
+ clearDiffPresentation();
+
+ boolean shouldHighlight = getTextSettings().getHighlightPolicy() != HighlightPolicy.DO_NOT_HIGHLIGHT;
+ if (shouldHighlight) {
+ final DocumentContent content = getContent();
+ final Document document = content.getDocument();
+
+ int start = 0;
+ int end = document.getTextLength();
+ TextDiffType type = getSide().select(TextDiffType.DELETED, TextDiffType.INSERTED);
+
+ myHighlighters.add(DiffDrawUtil.createHighlighter(getEditor(), start, end, type, false));
+
+ int startLine = 0;
+ int endLine = getLineCount(document);
+
+ if (startLine != endLine) {
+ myHighlighters.add(DiffDrawUtil.createLineMarker(getEditor(), startLine, type, SeparatorPlacement.TOP));
+ myHighlighters.add(DiffDrawUtil.createLineMarker(getEditor(), endLine - 1, type, SeparatorPlacement.BOTTOM));
+ }
+ }
+
+ myInitialScrollHelper.onRediff();
+ }
+ };
+ }
+
+
+ private void clearDiffPresentation() {
+ myPanel.resetNotifications();
+
+ for (RangeHighlighter highlighter : myHighlighters) {
+ highlighter.dispose();
+ }
+ myHighlighters.clear();
+ }
+
+ //
+ // Impl
+ //
+
+ private void doScrollToChange(final boolean animated) {
+ DiffUtil.moveCaret(getEditor(), 0);
+ DiffUtil.scrollEditor(getEditor(), 0, animated);
+ }
+
+ protected boolean doScrollToContext(@NotNull DiffNavigationContext context) {
+ if (getSide().isLeft()) return false;
+
+ AllLinesIterator allLinesIterator = new AllLinesIterator();
+ NavigationContextChecker checker2 = new NavigationContextChecker(allLinesIterator, context);
+ int line = checker2.contextMatchCheck();
+ if (line == -1) return false;
+
+ scrollToLine(line);
+ return true;
+ }
+
+ //
+ // Misc
+ //
+
+ @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass")
+ public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ return OnesideTextDiffViewer.canShowRequest(context, request);
+ }
+
+ //
+ // Actions
+ //
+
+ private class MyReadOnlyLockAction extends TextDiffViewerUtil.EditorReadOnlyLockAction {
+ public MyReadOnlyLockAction() {
+ super(getContext(), getEditableEditors());
+ }
+ }
+
+ //
+ // Modification operations
+ //
+
+ private class MyHighlightPolicySettingAction extends TextDiffViewerUtil.HighlightPolicySettingAction {
+ public MyHighlightPolicySettingAction() {
+ super(getTextSettings());
+ }
+
+ @Override
+ protected void onSettingsChanged() {
+ rediff();
+ }
+ }
+
+ private class MyIgnorePolicySettingAction extends TextDiffViewerUtil.IgnorePolicySettingAction {
+ public MyIgnorePolicySettingAction() {
+ super(getTextSettings());
+ }
+
+ @Override
+ protected void onSettingsChanged() {
+ rediff();
+ }
+ }
+
+ //
+ // Scroll from annotate
+ //
+
+ private class AllLinesIterator implements Iterator<Pair<Integer, CharSequence>> {
+ @NotNull private final Document myDocument;
+ private int myLine = 0;
+
+ private AllLinesIterator() {
+ myDocument = getEditor().getDocument();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return myLine < getLineCount(myDocument);
+ }
+
+ @Override
+ public Pair<Integer, CharSequence> next() {
+ int offset1 = myDocument.getLineStartOffset(myLine);
+ int offset2 = myDocument.getLineEndOffset(myLine);
+
+ CharSequence text = myDocument.getImmutableCharSequence().subSequence(offset1, offset2);
+
+ Pair<Integer, CharSequence> pair = new Pair<Integer, CharSequence>(myLine, text);
+ myLine++;
+
+ return pair;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ //
+ // Helpers
+ //
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (DiffDataKeys.CURRENT_CHANGE_RANGE.is(dataId)) {
+ int lineCount = getLineCount(getEditor().getDocument());
+ return new LineRange(0, lineCount);
+ }
+ return super.getData(dataId);
+ }
+
+ private class MyInitialScrollHelper extends MyInitialScrollPositionHelper {
+ @Override
+ protected boolean doScrollToChange() {
+ if (myScrollToChange == null) return false;
+ SimpleOnesideDiffViewer.this.doScrollToChange(false);
+ return true;
+ }
+
+ @Override
+ protected boolean doScrollToFirstChange() {
+ SimpleOnesideDiffViewer.this.doScrollToChange(false);
+ return true;
+ }
+
+ @Override
+ protected boolean doScrollToContext() {
+ if (myNavigationContext == null) return false;
+ return SimpleOnesideDiffViewer.this.doScrollToContext(myNavigationContext);
+ }
+
+ @Override
+ protected boolean doScrollToPosition() {
+ if (myCaretPosition == null) return false;
+
+ LogicalPosition position = getSide().select(myCaretPosition);
+ getEditor().getCaretModel().moveToLogicalPosition(position);
+
+ if (myEditorsPosition != null && myEditorsPosition.isSame(position)) {
+ DiffUtil.scrollToPoint(getEditor(), myEditorsPosition.myPoints[0], false);
+ }
+ else {
+ DiffUtil.scrollToCaret(getEditor(), false);
+ }
+ return true;
+ }
+
+ @Nullable
+ @Override
+ protected LogicalPosition[] getCaretPositions() {
+ int index = getSide().getIndex();
+ int otherIndex = getSide().other().getIndex();
+
+ LogicalPosition[] carets = new LogicalPosition[2];
+ carets[index] = getEditor().getCaretModel().getLogicalPosition();
+ carets[otherIndex] = new LogicalPosition(0, 0);
+ return carets;
+ }
+ }
+}
public boolean processChange(int oldLine1, int oldLine2, int shift, @NotNull ThreeSide side) {
int line1 = getStartLine(side);
int line2 = getEndLine(side);
+ int sideIndex = side.getIndex();
- if (line2 <= oldLine1) return false;
- if (line1 >= oldLine2) {
- myLineStartShifts[side.getIndex()] += shift;
- myLineEndShifts[side.getIndex()] += shift;
- return false;
- }
-
- if (line1 <= oldLine1 && line2 >= oldLine2) {
- myLineEndShifts[side.getIndex()] += shift;
- return false;
- }
+ DiffUtil.UpdatedLineRange newRange = DiffUtil.updateRangeOnModification(line1, line2, oldLine1, oldLine2, shift);
+ myLineStartShifts[sideIndex] += newRange.startLine - line1;
+ myLineEndShifts[sideIndex] += newRange.endLine - line2;
- return true;
+ return newRange.damaged;
}
//
import com.intellij.diff.DiffContext;
import com.intellij.diff.comparison.ByLine;
+import com.intellij.diff.comparison.ComparisonMergeUtil;
import com.intellij.diff.comparison.ComparisonPolicy;
import com.intellij.diff.comparison.DiffTooBigException;
-import com.intellij.diff.comparison.MergeUtil;
import com.intellij.diff.comparison.iterables.FairDiffIterable;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.contents.DocumentContent;
import com.intellij.diff.requests.DiffRequest;
import com.intellij.diff.tools.util.*;
import com.intellij.diff.tools.util.base.IgnorePolicy;
-import com.intellij.diff.tools.util.threeside.ThreesideTextDiffViewer;
+import com.intellij.diff.tools.util.base.TextDiffViewerUtil;
+import com.intellij.diff.tools.util.side.ThreesideTextDiffViewer;
+import com.intellij.diff.util.DiffDividerDrawUtil;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.diff.util.Side;
+import com.intellij.diff.util.ThreeSide;
import com.intellij.diff.util.*;
import com.intellij.diff.util.DiffUserDataKeysEx.ScrollToPolicy;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.Separator;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.DiffBundle;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.event.DocumentEvent;
@NotNull private final List<SimpleThreesideDiffChange> myDiffChanges = new ArrayList<SimpleThreesideDiffChange>();
@NotNull private final List<SimpleThreesideDiffChange> myInvalidDiffChanges = new ArrayList<SimpleThreesideDiffChange>();
+ private int myChangesCount = -1;
+ private int myConflictsCount = -1;
@NotNull private final MyFoldingModel myFoldingModel;
@NotNull private final MyInitialScrollHelper myInitialScrollHelper = new MyInitialScrollHelper();
group.add(new MyIgnorePolicySettingAction());
//group.add(new MyHighlightPolicySettingAction()); // TODO
group.add(new MyToggleExpandByDefaultAction());
- group.add(new ToggleAutoScrollAction());
- group.add(new EditorReadOnlyLockAction());
+ group.add(new MyToggleAutoScrollAction());
+ group.add(new MyEditorReadOnlyLockAction());
group.add(myEditorSettingsAction);
group.add(Separator.getInstance());
//group.add(Separator.getInstance());
//group.add(new MyHighlightPolicySettingAction().getPopupGroup());
group.add(Separator.getInstance());
- group.add(new ToggleAutoScrollAction());
+ group.add(new MyToggleAutoScrollAction());
group.add(new MyToggleExpandByDefaultAction());
return group;
// Diff
//
+ @NotNull
+ public FoldingModelSupport.Settings getFoldingModelSettings() {
+ return TextDiffViewerUtil.getFoldingModelSettings(myContext);
+ }
+
@Override
protected void onSlowRediff() {
super.onSlowRediff();
ComparisonPolicy comparisonPolicy = getIgnorePolicy().getComparisonPolicy();
FairDiffIterable fragments1 = ByLine.compareTwoStepFair(sequences[1], sequences[0], comparisonPolicy, indicator);
FairDiffIterable fragments2 = ByLine.compareTwoStepFair(sequences[1], sequences[2], comparisonPolicy, indicator);
- List<MergeLineFragment> mergeFragments = MergeUtil.buildFair(fragments1, fragments2, indicator);
+ List<MergeLineFragment> mergeFragments = ComparisonMergeUtil.buildFair(fragments1, fragments2, indicator);
return apply(mergeFragments, comparisonPolicy);
}
- catch (DiffTooBigException ignore) {
+ catch (DiffTooBigException e) {
return applyNotification(DiffNotifications.DIFF_TOO_BIG);
}
- catch (ProcessCanceledException ignore) {
- return applyNotification(DiffNotifications.OPERATION_CANCELED);
+ catch (ProcessCanceledException e) {
+ throw e;
}
catch (Throwable e) {
LOG.error(e);
myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
clearDiffPresentation();
+ myChangesCount = 0;
+ myConflictsCount = 0;
for (MergeLineFragment fragment : fragments) {
- myDiffChanges.add(new SimpleThreesideDiffChange(fragment, getEditors(), comparisonPolicy));
+ SimpleThreesideDiffChange change = new SimpleThreesideDiffChange(fragment, getEditors(), comparisonPolicy);
+ myDiffChanges.add(change);
+ if (change.getDiffType() != TextDiffType.CONFLICT) myChangesCount++;
+ if (change.getDiffType() == TextDiffType.CONFLICT) myConflictsCount++;
}
myFoldingModel.install(fragments, myRequest, getFoldingModelSettings());
}
myInvalidDiffChanges.clear();
+ myChangesCount = -1;
+ myConflictsCount = -1;
+
myFoldingModel.destroy();
myContentPanel.repaintDividers();
return;
}
- int offset1 = e.getOffset();
- int offset2 = e.getOffset() + e.getOldLength();
-
- if (StringUtil.endsWithChar(e.getOldFragment(), '\n') &&
- StringUtil.endsWithChar(e.getNewFragment(), '\n')) {
- offset2--;
- }
-
- int line1 = e.getDocument().getLineNumber(offset1);
- int line2 = e.getDocument().getLineNumber(offset2) + 1;
- int shift = StringUtil.countNewLines(e.getNewFragment()) - StringUtil.countNewLines(e.getOldFragment());
+ int line1 = e.getDocument().getLineNumber(e.getOffset());
+ int line2 = e.getDocument().getLineNumber(e.getOffset() + e.getOldLength()) + 1;
+ int shift = DiffUtil.countLinesShift(e);
List<SimpleThreesideDiffChange> invalid = new ArrayList<SimpleThreesideDiffChange>();
for (SimpleThreesideDiffChange change : myDiffChanges) {
// Getters
//
- private int getCurrentStartLine(@NotNull SimpleThreesideDiffChange change) {
- return change.getStartLine(getCurrentSide());
- }
-
- private int getCurrentEndLine(@NotNull SimpleThreesideDiffChange change) {
- return change.getEndLine(getCurrentSide());
- }
-
@NotNull
protected List<SimpleThreesideDiffChange> getDiffChanges() {
return myDiffChanges;
// Actions
//
- private class MyPrevNextDifferenceIterable implements PrevNextDifferenceIterable {
+ private class MyPrevNextDifferenceIterable extends PrevNextDifferenceIterableBase<SimpleThreesideDiffChange> {
+ @NotNull
@Override
- public boolean canGoNext() {
- if (myDiffChanges.isEmpty()) return false;
-
- EditorEx editor = getCurrentEditor();
- int line = editor.getCaretModel().getLogicalPosition().line;
- if (line == editor.getDocument().getLineCount() - 1) return false;
-
- SimpleThreesideDiffChange lastChange = myDiffChanges.get(myDiffChanges.size() - 1);
- if (getCurrentStartLine(lastChange) <= line) return false;
-
- return true;
+ protected List<SimpleThreesideDiffChange> getChanges() {
+ return myDiffChanges;
}
+ @NotNull
@Override
- public void goNext() {
- EditorEx editor = getCurrentEditor();
-
- int line = editor.getCaretModel().getLogicalPosition().line;
-
- SimpleThreesideDiffChange next = null;
- for (int i = 0; i < myDiffChanges.size(); i++) {
- SimpleThreesideDiffChange change = myDiffChanges.get(i);
- if (getCurrentStartLine(change) <= line) continue;
-
- next = change;
- break;
- }
-
- assert next != null;
- doScrollToChange(next, true);
+ protected EditorEx getEditor() {
+ return getCurrentEditor();
}
@Override
- public boolean canGoPrev() {
- if (myDiffChanges.isEmpty()) return false;
-
- EditorEx editor = getCurrentEditor();
- int line = editor.getCaretModel().getLogicalPosition().line;
- if (line == 0) return false;
-
- SimpleThreesideDiffChange firstChange = myDiffChanges.get(0);
- if (getCurrentEndLine(firstChange) > line) return false;
- if (getCurrentStartLine(firstChange) >= line) return false;
-
- return true;
+ protected int getStartLine(@NotNull SimpleThreesideDiffChange change) {
+ return change.getStartLine(getCurrentSide());
}
@Override
- public void goPrev() {
- EditorEx editor = getCurrentEditor();
-
- int line = editor.getCaretModel().getLogicalPosition().line;
-
- SimpleThreesideDiffChange prev = null;
- for (int i = 0; i < myDiffChanges.size(); i++) {
- SimpleThreesideDiffChange change = myDiffChanges.get(i);
-
- SimpleThreesideDiffChange next = i < myDiffChanges.size() - 1 ? myDiffChanges.get(i + 1) : null;
- if (next == null || getCurrentEndLine(next) > line || getCurrentStartLine(next) >= line) {
- prev = change;
- break;
- }
- }
+ protected int getEndLine(@NotNull SimpleThreesideDiffChange change) {
+ return change.getEndLine(getCurrentSide());
+ }
- assert prev != null;
- doScrollToChange(prev, true);
+ @Override
+ protected void scrollToChange(@NotNull SimpleThreesideDiffChange change) {
+ doScrollToChange(change, true);
}
}
- private class MyToggleExpandByDefaultAction extends ToggleExpandByDefaultAction {
+ private class MyToggleExpandByDefaultAction extends TextDiffViewerUtil.ToggleExpandByDefaultAction {
+ public MyToggleExpandByDefaultAction() {
+ super(getTextSettings());
+ }
+
@Override
protected void expandAll(boolean expand) {
myFoldingModel.expandAll(expand);
}
}
- private class MyIgnorePolicySettingAction extends IgnorePolicySettingAction {
+ private class MyIgnorePolicySettingAction extends TextDiffViewerUtil.IgnorePolicySettingAction {
+ public MyIgnorePolicySettingAction() {
+ super(getTextSettings());
+ }
+
@NotNull
@Override
protected IgnorePolicy getCurrentSetting() {
settings.remove(IgnorePolicy.IGNORE_WHITESPACES_CHUNKS);
return settings;
}
+
+ @Override
+ protected void onSettingsChanged() {
+ rediff();
+ }
+ }
+
+ protected class MyEditorReadOnlyLockAction extends TextDiffViewerUtil.EditorReadOnlyLockAction {
+ public MyEditorReadOnlyLockAction() {
+ super(getContext(), getEditableEditors());
+ }
}
//
}
private class MyStatusPanel extends StatusPanel {
+ @Nullable
@Override
- protected int getChangesCount() {
- return myDiffChanges.size() + myInvalidDiffChanges.size();
+ protected String getMessage() {
+ if (myChangesCount < 0 || myConflictsCount < 0) return null;
+ if (myChangesCount == 0 && myConflictsCount == 0) {
+ return DiffBundle.message("merge.dialog.all.conflicts.resolved.message.text");
+ }
+ return makeCounterWord(myChangesCount, "change") + ". " + makeCounterWord(myConflictsCount, "conflict");
+ }
+
+ @NotNull
+ private String makeCounterWord(int number, @NotNull String word) {
+ if (number == 0) {
+ return "No " + StringUtil.pluralize(word);
+ }
+ return number + " " + StringUtil.pluralize(word, number);
}
}
import com.intellij.diff.DiffContext;
import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.holders.EditorHolder;
import com.intellij.diff.util.DiffUserDataKeys;
import com.intellij.diff.util.Side;
import com.intellij.diff.util.ThreeSide;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileEditor.FileEditor;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.FocusAdapter;
public static class TwosideFocusTrackerSupport {
@NotNull private Side myCurrentSide;
- private final boolean myDumbMode;
- @Nullable private final MyFocusListener myListener1;
- @Nullable private final MyFocusListener myListener2;
+ public TwosideFocusTrackerSupport(@NotNull List<? extends EditorHolder> holders) {
+ assert holders.size() == 2;
- public TwosideFocusTrackerSupport(@Nullable Editor editor1, @Nullable Editor editor2) {
- this(getComponent(editor1), getComponent(editor2));
- }
-
- public TwosideFocusTrackerSupport(@Nullable FileEditor editor1, @Nullable FileEditor editor2) {
- this(getComponent(editor1), getComponent(editor2));
- }
-
- public TwosideFocusTrackerSupport(@Nullable JComponent component1, @Nullable JComponent component2) {
- assert component1 != null || component2 != null;
- myCurrentSide = component2 != null ? Side.RIGHT : Side.LEFT;
+ myCurrentSide = Side.RIGHT;
- myDumbMode = component1 == null || component2 == null;
- if (!myDumbMode) {
- myListener1 = new MyFocusListener(Side.LEFT);
- component1.addFocusListener(myListener1);
-
- myListener2 = new MyFocusListener(Side.RIGHT);
- component2.addFocusListener(myListener2);
- }
- else {
- myListener1 = null;
- myListener2 = null;
- }
+ addListener(holders, Side.LEFT);
+ addListener(holders, Side.RIGHT);
}
@NotNull
}
public void setCurrentSide(@NotNull Side side) {
- if (myDumbMode) return;
myCurrentSide = side;
}
}
public void updateContextHints(@NotNull DiffRequest request, @NotNull DiffContext context) {
- if (myDumbMode) return;
context.putUserData(DiffUserDataKeys.PREFERRED_FOCUS_SIDE, myCurrentSide);
}
+ private void addListener(@NotNull List<? extends EditorHolder> holders, @NotNull Side side) {
+ side.select(holders).installFocusListener(new MyFocusListener(side));
+ }
+
private class MyFocusListener extends FocusAdapter {
@NotNull private final Side mySide;
public static class ThreesideFocusTrackerSupport {
@NotNull private ThreeSide myCurrentSide;
- private final boolean myDumbMode;
- @Nullable private final MyFocusListener myListener1;
- @Nullable private final MyFocusListener myListener2;
- @Nullable private final MyFocusListener myListener3;
-
- public ThreesideFocusTrackerSupport(@NotNull List<? extends Editor> editors) {
- this(editors.get(0), editors.get(1), editors.get(2));
- }
+ public ThreesideFocusTrackerSupport(@NotNull List<? extends EditorHolder> holders) {
+ myCurrentSide = ThreeSide.BASE;
- public ThreesideFocusTrackerSupport(@Nullable Editor editor1, @Nullable Editor editor2, @Nullable Editor editor3) {
- this(getComponent(editor1), getComponent(editor2), getComponent(editor3));
- }
-
- public ThreesideFocusTrackerSupport(@Nullable FileEditor editor1, @Nullable FileEditor editor2, @Nullable FileEditor editor3) {
- this(getComponent(editor1), getComponent(editor2), getComponent(editor3));
- }
-
- public ThreesideFocusTrackerSupport(@Nullable JComponent component1, @Nullable JComponent component2, @Nullable JComponent component3) {
- assert component1 != null || component2 != null || component3 != null;
- myCurrentSide = component2 != null ? ThreeSide.BASE : component1 != null ? ThreeSide.LEFT : ThreeSide.RIGHT;
-
- boolean c1 = component1 != null;
- boolean c2 = component2 != null;
- boolean c3 = component3 != null;
- myDumbMode = (!c1 && !c2) || (!c1 && !c3) || (!c2 && !c3); // only one not-null element
-
- if (!myDumbMode) {
- myListener1 = component1 != null ? new MyFocusListener(ThreeSide.LEFT) : null;
- if (component1 != null) component1.addFocusListener(myListener1);
-
- myListener2 = component2 != null ? new MyFocusListener(ThreeSide.BASE) : null;
- if (component2 != null) component2.addFocusListener(myListener2);
-
- myListener3 = component3 != null ? new MyFocusListener(ThreeSide.RIGHT) : null;
- if (component3 != null) component3.addFocusListener(myListener3);
- }
- else {
- myListener1 = null;
- myListener2 = null;
- myListener3 = null;
- }
+ addListener(holders, ThreeSide.LEFT);
+ addListener(holders, ThreeSide.BASE);
+ addListener(holders, ThreeSide.RIGHT);
}
@NotNull
}
public void setCurrentSide(@NotNull ThreeSide side) {
- if (myDumbMode || side.select(myListener1, myListener2, myListener3) == null) return;
myCurrentSide = side;
}
}
public void updateContextHints(@NotNull DiffRequest request, @NotNull DiffContext context) {
- if (myDumbMode) return;
context.putUserData(DiffUserDataKeys.PREFERRED_FOCUS_THREESIDE, myCurrentSide);
}
+ private void addListener(@NotNull List<? extends EditorHolder> holders, @NotNull ThreeSide side) {
+ side.select(holders).installFocusListener(new MyFocusListener(side));
+ }
+
private class MyFocusListener extends FocusAdapter {
@NotNull private final ThreeSide mySide;
}
}
}
-
- @Nullable
- private static JComponent getComponent(@Nullable Editor editor) {
- return editor != null ? editor.getContentComponent() : null;
- }
-
- @Nullable
- private static JComponent getComponent(@Nullable FileEditor editor) {
- return editor != null ? editor.getComponent() : null;
- }
}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.util;
+
+import com.intellij.ide.IdeEventQueue;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowFocusListener;
+
+public class KeyboardModifierListener {
+ private boolean myShiftPressed;
+ private boolean myCtrlPressed;
+ private boolean myAltPressed;
+
+ @Nullable private Window myWindow;
+
+ private final WindowFocusListener myWindowFocusListener = new WindowFocusListener() {
+ @Override
+ public void windowGainedFocus(WindowEvent e) {
+ resetState();
+ }
+
+ @Override
+ public void windowLostFocus(WindowEvent e) {
+ resetState();
+ }
+ };
+
+ public void init(@NotNull JComponent component, @NotNull Disposable disposable) {
+ assert myWindow == null;
+
+ Disposer.register(disposable, new Disposable() {
+ @Override
+ public void dispose() {
+ destroy();
+ }
+ });
+
+ // we can use KeyListener on Editors, but Ctrl+Click will not work with focus in other place.
+ // ex: commit dialog with focus in commit message
+ IdeEventQueue.getInstance().addPostprocessor(new IdeEventQueue.EventDispatcher() {
+ @Override
+ public boolean dispatch(AWTEvent e) {
+ if (e instanceof KeyEvent) {
+ onKeyEvent((KeyEvent)e);
+ }
+ return false;
+ }
+ }, disposable);
+
+ myWindow = UIUtil.getWindow(component);
+ if (myWindow != null) {
+ myWindow.addWindowFocusListener(myWindowFocusListener);
+ }
+ }
+
+ public void destroy() {
+ if (myWindow != null) {
+ myWindow.removeWindowFocusListener(myWindowFocusListener);
+ myWindow = null;
+ }
+ }
+
+ private void onKeyEvent(KeyEvent e) {
+ final int keyCode = e.getKeyCode();
+ if (keyCode == KeyEvent.VK_SHIFT) {
+ myShiftPressed = e.getID() == KeyEvent.KEY_PRESSED;
+ onModifiersChanged();
+ }
+ if (keyCode == KeyEvent.VK_CONTROL) {
+ myCtrlPressed = e.getID() == KeyEvent.KEY_PRESSED;
+ onModifiersChanged();
+ }
+ if (keyCode == KeyEvent.VK_ALT) {
+ myAltPressed = e.getID() == KeyEvent.KEY_PRESSED;
+ onModifiersChanged();
+ }
+ }
+
+ private void resetState() {
+ myShiftPressed = false;
+ myAltPressed = false;
+ myCtrlPressed = false;
+ onModifiersChanged();
+ }
+
+ public boolean isShiftPressed() {
+ return myShiftPressed;
+ }
+
+ public boolean isCtrlPressed() {
+ return myCtrlPressed;
+ }
+
+ public boolean isAltPressed() {
+ return myAltPressed;
+ }
+
+ public void onModifiersChanged() {
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.util;
+
+import com.intellij.openapi.editor.ex.EditorEx;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public abstract class PrevNextDifferenceIterableBase<T> implements PrevNextDifferenceIterable {
+ @NotNull
+ protected abstract List<T> getChanges();
+
+ @NotNull
+ protected abstract EditorEx getEditor();
+
+ protected abstract int getStartLine(@NotNull T change);
+
+ protected abstract int getEndLine(@NotNull T change);
+
+ protected abstract void scrollToChange(@NotNull T change);
+
+ @Override
+ public boolean canGoNext() {
+ List<T> changes = getChanges();
+ if (changes.isEmpty()) return false;
+
+ EditorEx editor = getEditor();
+ int line = editor.getCaretModel().getLogicalPosition().line;
+ if (line == editor.getDocument().getLineCount() - 1) return false;
+
+ T lastChange = changes.get(changes.size() - 1);
+ if (getStartLine(lastChange) <= line) return false;
+
+ return true;
+ }
+
+ @Override
+ public void goNext() {
+ List<T> changes = getChanges();
+ int line = getEditor().getCaretModel().getLogicalPosition().line;
+
+ T next = null;
+ for (int i = 0; i < changes.size(); i++) {
+ T change = changes.get(i);
+ if (getStartLine(change) <= line) continue;
+
+ next = change;
+ break;
+ }
+
+ assert next != null;
+ scrollToChange(next);
+ }
+
+ @Override
+ public boolean canGoPrev() {
+ List<T> changes = getChanges();
+ if (changes.isEmpty()) return false;
+
+ int line = getEditor().getCaretModel().getLogicalPosition().line;
+ if (line == 0) return false;
+
+ T firstChange = changes.get(0);
+ if (getEndLine(firstChange) > line) return false;
+ if (getStartLine(firstChange) >= line) return false;
+
+ return true;
+ }
+
+ @Override
+ public void goPrev() {
+ List<T> changes = getChanges();
+ int line = getEditor().getCaretModel().getLogicalPosition().line;
+
+ T prev = null;
+ for (int i = 0; i < changes.size(); i++) {
+ T change = changes.get(i);
+
+ T next = i < changes.size() - 1 ? changes.get(i + 1) : null;
+ if (next == null || getEndLine(next) > line || getStartLine(next) >= line) {
+ prev = change;
+ break;
+ }
+ }
+
+ assert prev != null;
+ scrollToChange(prev);
+ }
+}
\ No newline at end of file
package com.intellij.diff.tools.util;
import com.intellij.openapi.diff.DiffBundle;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.ui.AnimatedIcon;
import com.intellij.util.ui.AsyncProcessIcon;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
-public abstract class StatusPanel extends JPanel {
+public class StatusPanel extends JPanel {
private final JLabel myTextLabel;
private final AnimatedIcon myBusySpinner;
}
public void update() {
- int count = getChangesCount();
- myTextLabel.setVisible(count != -1);
- myTextLabel.setText(DiffBundle.message("diff.count.differences.status.text", count));
+ String message = getMessage();
+ myTextLabel.setVisible(message != null);
+ myTextLabel.setText(StringUtil.notNullize(message));
}
public void setBusy(boolean busy) {
}
}
- protected abstract int getChangesCount();
+ @Nullable
+ protected String getMessage() {
+ int count = getChangesCount();
+ if (count == -1) return null;
+ return DiffBundle.message("diff.count.differences.status.text", count);
+ }
+
+ protected int getChangesCount() {
+ return -1;
+ }
}
private boolean myDisabled = false;
private boolean myDuringSyncScroll = false;
+ public TwosideSyncScrollSupport(@NotNull List<? extends Editor> editors, @NotNull SyncScrollable scrollable) {
+ this(Side.LEFT.select(editors), Side.RIGHT.select(editors), scrollable);
+ }
+
public TwosideSyncScrollSupport(@NotNull Editor editor1, @NotNull Editor editor2, @NotNull SyncScrollable scrollable) {
myEditor1 = editor1;
myEditor2 = editor2;
return myRequest;
}
+ @NotNull
+ public DiffContext getContext() {
+ return myContext;
+ }
+
public boolean isDisposed() {
return myDisposed;
}
package com.intellij.diff.tools.util.base;
import com.intellij.diff.DiffContext;
-import com.intellij.diff.actions.impl.SetEditorSettingsAction;
+import com.intellij.diff.contents.DiffContent;
+import com.intellij.diff.contents.DocumentContent;
import com.intellij.diff.requests.ContentDiffRequest;
import com.intellij.diff.tools.util.FoldingModelSupport;
import com.intellij.diff.tools.util.base.TextDiffSettingsHolder.TextDiffSettings;
import com.intellij.diff.util.DiffUserDataKeysEx;
import com.intellij.diff.util.DiffUtil;
import com.intellij.icons.AllIcons;
+import com.intellij.openapi.Disposable;
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.actions.EditorActionUtil;
import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.ui.ToggleActionButton;
import com.intellij.util.EditorPopupHandler;
import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.CalledInAwt;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Arrays;
import java.util.List;
-public abstract class TextDiffViewerBase extends ListenerDiffViewerBase {
+public class TextDiffViewerUtil {
+ public static final Logger LOG = Logger.getInstance(TextDiffViewerUtil.class);
public static final Key<Boolean> READ_ONLY_LOCK_KEY = Key.create("ReadOnlyLockAction");
- @NotNull private final TextDiffSettings myTextSettings;
-
- @NotNull private final MyFontSizeListener myFontSizeListener = new MyFontSizeListener();
-
- @NotNull private final MyEditorMouseListener myEditorPopupListener = new MyEditorMouseListener();
- @NotNull private List<AnAction> myEditorPopupActions;
-
- public TextDiffViewerBase(@NotNull DiffContext context, @NotNull ContentDiffRequest request) {
- super(context, request);
-
- myTextSettings = initTextSettings(context);
- }
-
- @Override
- protected void onInit() {
- super.onInit();
- myEditorPopupActions = createEditorPopupActions();
- installEditorListeners();
- }
-
- @Override
- protected void onDispose() {
- destroyEditorListeners();
- super.onDispose();
- }
-
- @CalledInAwt
- protected void installEditorListeners() {
- List<? extends EditorEx> editors = getEditors();
-
- for (EditorEx editor : editors) {
- if (editor != null) editor.addEditorMouseListener(myEditorPopupListener);
- }
-
- if (editors.size() > 1) {
- for (EditorEx editor : editors) {
- if (editor != null) editor.addPropertyChangeListener(myFontSizeListener);
- }
- }
- }
-
- @CalledInAwt
- protected void destroyEditorListeners() {
- List<? extends EditorEx> editors = getEditors();
-
- for (EditorEx editor : editors) {
- if (editor != null) editor.removeEditorMouseListener(myEditorPopupListener);
- }
-
- if (editors.size() > 1) {
- for (EditorEx editor : editors) {
- if (editor != null) editor.removePropertyChangeListener(myFontSizeListener);
- }
- }
- }
-
- //
- // Abstract
- //
-
@NotNull
- protected abstract List<? extends EditorEx> getEditors();
-
- @NotNull
- protected List<AnAction> createEditorPopupActions() {
+ public static List<AnAction> createEditorPopupActions() {
List<AnAction> result = new ArrayList<AnAction>();
result.add(ActionManager.getInstance().getAction("CompareClipboardWithSelection"));
return result;
}
- @CalledInAwt
- protected void onSettingsChanged() {
- rediff();
- }
-
- //
- // Impl
- //
-
@NotNull
- protected TextDiffSettings getTextSettings() {
- return myTextSettings;
- }
-
- @NotNull
- protected FoldingModelSupport.Settings getFoldingModelSettings() {
- TextDiffSettings settings = getTextSettings();
+ public static FoldingModelSupport.Settings getFoldingModelSettings(@NotNull DiffContext context) {
+ TextDiffSettings settings = getTextSettings(context);
return new FoldingModelSupport.Settings(settings.getContextRange(), settings.isExpandByDefault());
}
@NotNull
- private static TextDiffSettings initTextSettings(@NotNull DiffContext context) {
+ public static TextDiffSettings getTextSettings(@NotNull DiffContext context) {
TextDiffSettings settings = context.getUserData(TextDiffSettingsHolder.KEY);
if (settings == null) {
settings = TextDiffSettings.getSettings(context.getUserData(DiffUserDataKeysEx.PLACE));
return settings;
}
- //
- // Helpers
- //
-
@NotNull
- protected boolean[] checkForceReadOnly() {
- int contentCount = myRequest.getContents().size();
+ public static boolean[] checkForceReadOnly(@NotNull DiffContext context, @NotNull ContentDiffRequest request) {
+ int contentCount = request.getContents().size();
boolean[] result = new boolean[contentCount];
- if (DiffUtil.isUserDataFlagSet(DiffUserDataKeys.FORCE_READ_ONLY, myRequest, myContext)) {
+ if (DiffUtil.isUserDataFlagSet(DiffUserDataKeys.FORCE_READ_ONLY, request, context)) {
Arrays.fill(result, true);
return result;
}
- boolean[] data = myRequest.getUserData(DiffUserDataKeys.FORCE_READ_ONLY_CONTENTS);
+ boolean[] data = request.getUserData(DiffUserDataKeys.FORCE_READ_ONLY_CONTENTS);
if (data != null && data.length == contentCount) {
return data;
}
return result;
}
- private class MyFontSizeListener implements PropertyChangeListener {
- private boolean myDuringUpdate = false;
-
- public void propertyChange(PropertyChangeEvent evt) {
- if (myDuringUpdate) return;
-
- if (!EditorEx.PROP_FONT_SIZE.equals(evt.getPropertyName())) return;
- if (evt.getOldValue().equals(evt.getNewValue())) return;
- int fontSize = ((Integer)evt.getNewValue()).intValue();
-
- for (EditorEx editor : getEditors()) {
- if (editor != null && evt.getSource() != editor) updateEditor(editor, fontSize);
+ public static void checkDifferentDocuments(@NotNull ContentDiffRequest request) {
+ // Actually, this should be a valid case. But it has little practical sense and will require explicit checks everywhere.
+ // Some listeners will be processed once instead of 2 times, some listeners will cause illegal document modifications.
+ List<DiffContent> contents = request.getContents();
+
+ boolean sameDocuments = false;
+ for (int i = 0; i < contents.size(); i++) {
+ for (int j = i + 1; j < contents.size(); j++) {
+ DiffContent content1 = contents.get(i);
+ DiffContent content2 = contents.get(j);
+ if (!(content1 instanceof DocumentContent)) continue;
+ if (!(content2 instanceof DocumentContent)) continue;
+ sameDocuments |= ((DocumentContent)content1).getDocument() == ((DocumentContent)content2).getDocument();
}
}
- public void updateEditor(@NotNull EditorEx editor, int fontSize) {
- try {
- myDuringUpdate = true;
- editor.setFontSize(fontSize);
- }
- finally {
- myDuringUpdate = false;
+ if (sameDocuments) {
+ StringBuilder message = new StringBuilder();
+ message.append("DiffRequest with same documents detected\n");
+ message.append(request.toString()).append("\n");
+ for (DiffContent content : contents) {
+ message.append(content.toString()).append("\n");
}
- }
- }
-
- protected class MySetEditorSettingsAction extends SetEditorSettingsAction {
- public MySetEditorSettingsAction() {
- super(myTextSettings, getEditors());
+ LOG.error(new Throwable(message.toString()));
}
}
//
// TODO: pretty icons ?
- protected static abstract class ComboBoxSettingAction<T> extends ComboBoxAction implements DumbAware {
+ public static abstract class ComboBoxSettingAction<T> extends ComboBoxAction implements DumbAware {
private DefaultActionGroup myChildren;
public ComboBoxSettingAction() {
}
}
- protected class HighlightPolicySettingAction extends ComboBoxSettingAction<HighlightPolicy> {
- public HighlightPolicySettingAction() {
+ public static abstract class HighlightPolicySettingAction extends ComboBoxSettingAction<HighlightPolicy> {
+ @NotNull protected final TextDiffSettings mySettings;
+
+ public HighlightPolicySettingAction(@NotNull TextDiffSettings settings) {
+ mySettings = settings;
}
@Override
protected void applySetting(@NotNull HighlightPolicy setting, @NotNull AnActionEvent e) {
if (getCurrentSetting() == setting) return;
- getTextSettings().setHighlightPolicy(setting);
+ mySettings.setHighlightPolicy(setting);
update(e);
onSettingsChanged();
}
@NotNull
@Override
protected HighlightPolicy getCurrentSetting() {
- return getTextSettings().getHighlightPolicy();
+ return mySettings.getHighlightPolicy();
}
@NotNull
protected List<HighlightPolicy> getAvailableSettings() {
return Arrays.asList(HighlightPolicy.values());
}
+
+ protected abstract void onSettingsChanged();
}
- protected class IgnorePolicySettingAction extends ComboBoxSettingAction<IgnorePolicy> {
- public IgnorePolicySettingAction() {
+ public static abstract class IgnorePolicySettingAction extends ComboBoxSettingAction<IgnorePolicy> {
+ @NotNull protected final TextDiffSettings mySettings;
+
+ public IgnorePolicySettingAction(@NotNull TextDiffSettings settings) {
+ mySettings = settings;
}
@Override
protected void applySetting(@NotNull IgnorePolicy setting, @NotNull AnActionEvent e) {
if (getCurrentSetting() == setting) return;
- getTextSettings().setIgnorePolicy(setting);
+ mySettings.setIgnorePolicy(setting);
update(e);
onSettingsChanged();
}
@NotNull
@Override
protected IgnorePolicy getCurrentSetting() {
- return getTextSettings().getIgnorePolicy();
+ return mySettings.getIgnorePolicy();
}
@NotNull
protected List<IgnorePolicy> getAvailableSettings() {
return Arrays.asList(IgnorePolicy.values());
}
+
+ protected abstract void onSettingsChanged();
}
- protected class ToggleAutoScrollAction extends ToggleActionButton implements DumbAware {
- public ToggleAutoScrollAction() {
+ public static class ToggleAutoScrollAction extends ToggleActionButton implements DumbAware {
+ @NotNull protected final TextDiffSettings mySettings;
+
+ public ToggleAutoScrollAction(@NotNull TextDiffSettings settings) {
super("Synchronize Scrolling", AllIcons.Actions.SynchronizeScrolling);
+ mySettings = settings;
setEnabledInModalContext(true);
}
@Override
public boolean isSelected(AnActionEvent e) {
- return getTextSettings().isEnableSyncScroll();
+ return mySettings.isEnableSyncScroll();
}
@Override
public void setSelected(AnActionEvent e, boolean state) {
- getTextSettings().setEnableSyncScroll(state);
+ mySettings.setEnableSyncScroll(state);
}
}
- protected abstract class ToggleExpandByDefaultAction extends ToggleActionButton implements DumbAware {
- public ToggleExpandByDefaultAction() {
+ public static abstract class ToggleExpandByDefaultAction extends ToggleActionButton implements DumbAware {
+ @NotNull protected final TextDiffSettings mySettings;
+
+ public ToggleExpandByDefaultAction(@NotNull TextDiffSettings settings) {
super("Collapse unchanged fragments", AllIcons.Actions.Collapseall);
+ mySettings = settings;
setEnabledInModalContext(true);
}
@Override
public boolean isVisible() {
- return getTextSettings().getContextRange() != -1;
+ return mySettings.getContextRange() != -1;
}
@Override
public boolean isSelected(AnActionEvent e) {
- return !getTextSettings().isExpandByDefault();
+ return !mySettings.isExpandByDefault();
}
@Override
public void setSelected(AnActionEvent e, boolean state) {
boolean expand = !state;
- if (getTextSettings().isExpandByDefault() == expand) return;
- getTextSettings().setExpandByDefault(expand);
+ if (mySettings.isExpandByDefault() == expand) return;
+ mySettings.setExpandByDefault(expand);
expandAll(expand);
}
protected abstract void expandAll(boolean expand);
}
- protected abstract class ReadOnlyLockAction extends ToggleAction implements DumbAware {
- public ReadOnlyLockAction() {
+ public static abstract class ReadOnlyLockAction extends ToggleAction implements DumbAware {
+ @NotNull protected final DiffContext myContext;
+
+ public ReadOnlyLockAction(@NotNull DiffContext context) {
super("Disable editing", null, AllIcons.Nodes.Padlock);
+ myContext = context;
setEnabledInModalContext(true);
}
protected abstract boolean canEdit();
}
- protected class EditorReadOnlyLockAction extends ReadOnlyLockAction {
+ public static class EditorReadOnlyLockAction extends ReadOnlyLockAction {
private final List<? extends EditorEx> myEditableEditors;
- public EditorReadOnlyLockAction() {
- this(getEditableEditors(getEditors()));
- }
-
- public EditorReadOnlyLockAction(@NotNull List<? extends EditorEx> editableEditors) {
+ public EditorReadOnlyLockAction(@NotNull DiffContext context, @NotNull List<? extends EditorEx> editableEditors) {
+ super(context);
myEditableEditors = editableEditors;
init();
}
}
@NotNull
- protected static List<? extends EditorEx> getEditableEditors(@NotNull List<? extends EditorEx> editors) {
+ public static List<? extends EditorEx> getEditableEditors(@NotNull List<? extends EditorEx> editors) {
return ContainerUtil.filter(editors, new Condition<EditorEx>() {
@Override
public boolean value(EditorEx editor) {
});
}
- private final class MyEditorMouseListener extends EditorPopupHandler {
+ public static class EditorFontSizeSynchronizer implements PropertyChangeListener {
+ @NotNull private final List<? extends EditorEx> myEditors;
+
+ private boolean myDuringUpdate = false;
+
+ public EditorFontSizeSynchronizer(@NotNull List<? extends EditorEx> editors) {
+ myEditors = editors;
+ }
+
+ public void install(@NotNull Disposable disposable) {
+ if (ContainerUtil.skipNulls(myEditors).size() < 2) return;
+
+ for (EditorEx editor : myEditors) {
+ if (editor == null) continue;
+ editor.addPropertyChangeListener(this, disposable);
+ }
+ }
+
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (myDuringUpdate) return;
+
+ if (!EditorEx.PROP_FONT_SIZE.equals(evt.getPropertyName())) return;
+ if (evt.getOldValue().equals(evt.getNewValue())) return;
+ int fontSize = ((Integer)evt.getNewValue()).intValue();
+
+ for (EditorEx editor : myEditors) {
+ if (editor != null && evt.getSource() != editor) updateEditor(editor, fontSize);
+ }
+ }
+
+ public void updateEditor(@NotNull EditorEx editor, int fontSize) {
+ try {
+ myDuringUpdate = true;
+ editor.setFontSize(fontSize);
+ }
+ finally {
+ myDuringUpdate = false;
+ }
+ }
+ }
+
+ public static class EditorActionsPopup extends EditorPopupHandler {
+ @NotNull private final List<? extends AnAction> myEditorPopupActions;
+
+ public EditorActionsPopup(@NotNull List<? extends AnAction> editorPopupActions) {
+ myEditorPopupActions = editorPopupActions;
+ }
+
+ public void install(@NotNull List<? extends Editor> editors) {
+ for (Editor editor : editors) {
+ if (editor == null) continue;
+ editor.addEditorMouseListener(this);
+ }
+ }
+
@Override
public void invokePopup(final EditorMouseEvent event) {
if (myEditorPopupActions.isEmpty()) return;
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.diff.tools.binary;
+package com.intellij.diff.tools.util.side;
-import com.intellij.diff.tools.util.twoside.TwosideContentPanel;
-import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.diff.tools.holders.EditorHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.List;
+import java.awt.*;
-public class BinaryContentPanel extends TwosideContentPanel {
- public BinaryContentPanel(@NotNull List<JComponent> titleComponents,
- @Nullable FileEditor editor1,
- @Nullable FileEditor editor2) {
- super(titleComponents, getComponent(editor1), getComponent(editor2));
- }
-
- @Nullable
- private static JComponent getComponent(@Nullable FileEditor editor) {
- return editor != null ? editor.getComponent() : null;
+public class HolderPanel extends JPanel {
+ public HolderPanel(@NotNull EditorHolder holder, @Nullable JComponent title) {
+ super(new BorderLayout());
+ add(holder.getComponent(), BorderLayout.CENTER);
+ if (title != null) add(title, BorderLayout.NORTH);
}
}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.util.side;
+
+import com.intellij.diff.tools.holders.EditorHolder;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class OnesideContentPanel extends JPanel {
+ public OnesideContentPanel(@NotNull EditorHolder holder, @NotNull JComponent titleComponent) {
+ super(new BorderLayout());
+
+ add(new HolderPanel(holder, titleComponent), BorderLayout.CENTER);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.util.side;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.contents.DiffContent;
+import com.intellij.diff.contents.EmptyContent;
+import com.intellij.diff.requests.ContentDiffRequest;
+import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.holders.EditorHolder;
+import com.intellij.diff.tools.holders.EditorHolderFactory;
+import com.intellij.diff.tools.util.DiffDataKeys;
+import com.intellij.diff.tools.util.SimpleDiffPanel;
+import com.intellij.diff.tools.util.base.ListenerDiffViewerBase;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.diff.util.Side;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.util.Disposer;
+import org.jetbrains.annotations.CalledInAwt;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.List;
+
+public abstract class OnesideDiffViewer<T extends EditorHolder> extends ListenerDiffViewerBase {
+ @NotNull protected final SimpleDiffPanel myPanel;
+ @NotNull protected final OnesideContentPanel myContentPanel;
+
+ @NotNull private final Side mySide;
+ @NotNull private final T myHolder;
+
+ public OnesideDiffViewer(@NotNull DiffContext context, @NotNull ContentDiffRequest request, @NotNull EditorHolderFactory<T> factory) {
+ super(context, request);
+
+ mySide = Side.fromRight(myRequest.getContents().get(0) instanceof EmptyContent);
+ myHolder = createEditorHolder(factory);
+
+ JComponent titlePanels = createTitle();
+ myContentPanel = new OnesideContentPanel(myHolder, titlePanels);
+
+ myPanel = new SimpleDiffPanel(myContentPanel, this, context);
+ }
+
+ @Override
+ @CalledInAwt
+ protected void onDispose() {
+ destroyEditorHolder();
+ super.onDispose();
+ }
+
+ //
+ // Editors
+ //
+
+ @NotNull
+ protected T createEditorHolder(@NotNull EditorHolderFactory<T> factory) {
+ DiffContent content = mySide.select(myRequest.getContents());
+ return factory.create(content, myContext);
+ }
+
+ private void destroyEditorHolder() {
+ Disposer.dispose(myHolder);
+ }
+
+ @NotNull
+ protected JComponent createTitle() {
+ List<JComponent> simpleTitles = DiffUtil.createSimpleTitles(myRequest);
+ return mySide.select(simpleTitles);
+ }
+
+ //
+ // Getters
+ //
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myPanel;
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ if (!myPanel.isGoodContent()) return null;
+ return getEditorHolder().getPreferredFocusedComponent();
+ }
+
+ @NotNull
+ public Side getSide() {
+ return mySide;
+ }
+
+ @NotNull
+ protected DiffContent getContent() {
+ return mySide.select(myRequest.getContents());
+ }
+
+ @NotNull
+ protected T getEditorHolder() {
+ return myHolder;
+ }
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) {
+ return DiffUtil.getVirtualFile(myRequest, mySide);
+ }
+ else if (DiffDataKeys.CURRENT_CONTENT.is(dataId)) {
+ return getContent();
+ }
+ return super.getData(dataId);
+ }
+
+ //
+ // Misc
+ //
+
+ @Nullable
+ @Override
+ protected OpenFileDescriptor getOpenFileDescriptor() {
+ return getContent().getOpenFileDescriptor();
+ }
+
+ public static <T extends EditorHolder> boolean canShowRequest(@NotNull DiffContext context,
+ @NotNull DiffRequest request,
+ @NotNull EditorHolderFactory<T> factory) {
+ if (!(request instanceof ContentDiffRequest)) return false;
+
+ List<DiffContent> contents = ((ContentDiffRequest)request).getContents();
+ if (contents.size() != 2) return false;
+
+ DiffContent content1 = contents.get(0);
+ DiffContent content2 = contents.get(1);
+
+ if (content1 instanceof EmptyContent && factory.wantShowContent(content2, context)) return true;
+ if (content2 instanceof EmptyContent && factory.wantShowContent(content1, context)) return true;
+ return false;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.util.side;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.actions.impl.OpenInEditorWithMouseAction;
+import com.intellij.diff.actions.impl.SetEditorSettingsAction;
+import com.intellij.diff.contents.DocumentContent;
+import com.intellij.diff.requests.ContentDiffRequest;
+import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.holders.EditorHolderFactory;
+import com.intellij.diff.tools.holders.TextEditorHolder;
+import com.intellij.diff.tools.util.DiffDataKeys;
+import com.intellij.diff.tools.util.base.InitialScrollPositionSupport;
+import com.intellij.diff.tools.util.base.TextDiffSettingsHolder;
+import com.intellij.diff.tools.util.base.TextDiffViewerUtil;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.diff.util.Side;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.CalledInAwt;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class OnesideTextDiffViewer extends OnesideDiffViewer<TextEditorHolder> {
+ public static final Logger LOG = Logger.getInstance(OnesideTextDiffViewer.class);
+
+ @NotNull private final List<? extends EditorEx> myEditableEditors;
+
+ @NotNull protected final SetEditorSettingsAction myEditorSettingsAction;
+
+ public OnesideTextDiffViewer(@NotNull DiffContext context, @NotNull ContentDiffRequest request) {
+ super(context, request, TextEditorHolder.TextEditorHolderFactory.INSTANCE);
+
+ myEditableEditors = TextDiffViewerUtil.getEditableEditors(getEditors());
+
+ myEditorSettingsAction = new SetEditorSettingsAction(getTextSettings(), getEditors());
+ myEditorSettingsAction.applyDefaults();
+
+ new MyOpenInEditorWithMouseAction().register(getEditors());
+ }
+
+ @Override
+ @CalledInAwt
+ protected void onInit() {
+ super.onInit();
+ installEditorListeners();
+ }
+
+ @Override
+ @CalledInAwt
+ protected void onDispose() {
+ destroyEditorListeners();
+ super.onDispose();
+ }
+
+ @NotNull
+ @Override
+ protected TextEditorHolder createEditorHolder(@NotNull EditorHolderFactory<TextEditorHolder> factory) {
+ TextEditorHolder holder = super.createEditorHolder(factory);
+
+ boolean[] forceReadOnly = TextDiffViewerUtil.checkForceReadOnly(myContext, myRequest);
+ if (forceReadOnly[0]) holder.getEditor().setViewer(true);
+
+ return holder;
+ }
+
+ @NotNull
+ @Override
+ protected JComponent createTitle() {
+ List<JComponent> textTitles = DiffUtil.createTextTitles(myRequest, ContainerUtil.list(getEditor(), getEditor()));
+ return getSide().select(textTitles);
+ }
+
+ //
+ // Diff
+ //
+
+ @NotNull
+ public TextDiffSettingsHolder.TextDiffSettings getTextSettings() {
+ return TextDiffViewerUtil.getTextSettings(myContext);
+ }
+
+ @NotNull
+ protected List<AnAction> createEditorPopupActions() {
+ return TextDiffViewerUtil.createEditorPopupActions();
+ }
+
+ //
+ // Listeners
+ //
+
+ @CalledInAwt
+ protected void installEditorListeners() {
+ new TextDiffViewerUtil.EditorActionsPopup(createEditorPopupActions()).install(getEditors());
+ }
+
+ @CalledInAwt
+ protected void destroyEditorListeners() {
+ }
+
+ //
+ // Getters
+ //
+
+ @NotNull
+ public List<? extends EditorEx> getEditors() {
+ return Collections.singletonList(getEditor());
+ }
+
+ @NotNull
+ protected List<? extends EditorEx> getEditableEditors() {
+ return myEditableEditors;
+ }
+
+ @NotNull
+ public EditorEx getEditor() {
+ return getEditorHolder().getEditor();
+ }
+
+ @NotNull
+ @Override
+ public DocumentContent getContent() {
+ //noinspection unchecked
+ return (DocumentContent)super.getContent();
+ }
+
+ //
+ // Abstract
+ //
+
+ @CalledInAwt
+ protected void scrollToLine(int line) {
+ DiffUtil.scrollEditor(getEditor(), line, false);
+ }
+
+ //
+ // Misc
+ //
+
+ @Nullable
+ @Override
+ protected OpenFileDescriptor getOpenFileDescriptor() {
+ int offset = getEditor().getCaretModel().getOffset();
+ return getContent().getOpenFileDescriptor(offset);
+ }
+
+ public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ return OnesideDiffViewer.canShowRequest(context, request, TextEditorHolder.TextEditorHolderFactory.INSTANCE);
+ }
+
+ //
+ // Actions
+ //
+
+ private class MyOpenInEditorWithMouseAction extends OpenInEditorWithMouseAction {
+ @Override
+ protected OpenFileDescriptor getDescriptor(@NotNull Editor editor, int line) {
+ if (editor != getEditor()) return null;
+
+ int offset = editor.logicalPositionToOffset(new LogicalPosition(line, 0));
+ return getContent().getOpenFileDescriptor(offset);
+ }
+ }
+
+ //
+ // Helpers
+ //
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) {
+ return getEditor();
+ }
+ return super.getData(dataId);
+ }
+
+ protected abstract class MyInitialScrollPositionHelper extends InitialScrollPositionSupport.TwosideInitialScrollHelper {
+ @NotNull
+ @Override
+ protected List<? extends Editor> getEditors() {
+ return OnesideTextDiffViewer.this.getEditors();
+ }
+
+ @Override
+ protected void disableSyncScroll(boolean value) {
+ }
+
+ @Override
+ protected boolean doScrollToLine() {
+ if (myScrollToLine == null) return false;
+ Side side = myScrollToLine.first;
+ if (side != getSide()) return false;
+
+ scrollToLine(myScrollToLine.second);
+ return true;
+ }
+ }
+}
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.diff.tools.util.threeside;
+package com.intellij.diff.tools.util.side;
+import com.intellij.diff.tools.holders.EditorHolder;
+import com.intellij.diff.tools.holders.TextEditorHolder;
import com.intellij.diff.tools.util.DiffSplitter;
import com.intellij.diff.tools.util.ThreeDiffSplitter;
import com.intellij.diff.util.Side;
+import com.intellij.diff.util.ThreeSide;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.util.ui.ButtonlessScrollBarUI;
import org.jetbrains.annotations.CalledInAwt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ThreesideContentPanel extends JPanel {
@NotNull private final ThreeDiffSplitter mySplitter;
+ @Nullable private final EditorEx myBaseEditor;
- public ThreesideContentPanel(@NotNull List<JComponent> editors, @NotNull List<JComponent> titleComponents) {
+ public ThreesideContentPanel(@NotNull List<? extends EditorHolder> holders, @NotNull List<JComponent> titleComponents) {
super(new BorderLayout());
- assert editors.size() == 3;
+ assert holders.size() == 3;
+ assert titleComponents.size() == 3;
+
+ EditorHolder baseHolder = ThreeSide.BASE.select(holders);
+ myBaseEditor = baseHolder instanceof TextEditorHolder ? ((TextEditorHolder)baseHolder).getEditor() : null;
ArrayList<JComponent> components = new ArrayList<JComponent>(3);
for (int i = 0; i < 3; i++) {
- components.add(new MyPanel(editors.get(i), titleComponents.get(i)));
+ components.add(new HolderPanel(holders.get(i), titleComponents.get(i)));
}
mySplitter = new ThreeDiffSplitter(components);
}
public void repaintDividers() {
+ if (myBaseEditor != null) myBaseEditor.getScrollPane().getVerticalScrollBar().repaint();
mySplitter.repaintDividers();
}
public void repaintDivider(@NotNull Side side) {
+ if (side == Side.RIGHT && myBaseEditor != null) myBaseEditor.getScrollPane().getVerticalScrollBar().repaint();
mySplitter.repaintDivider(side);
}
- private static class MyPanel extends JPanel {
- public MyPanel(@NotNull JComponent editor, @Nullable JComponent title) {
- super(new BorderLayout());
- add(editor, BorderLayout.CENTER);
- if (title != null) add(title, BorderLayout.NORTH);
- }
+ public void setScrollbarPainter(@NotNull ButtonlessScrollBarUI.ScrollbarRepaintCallback painter) {
+ if (myBaseEditor != null) myBaseEditor.registerScrollBarRepaintCallback(painter);
}
}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.util.side;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.DiffDialogHints;
+import com.intellij.diff.DiffManager;
+import com.intellij.diff.contents.DiffContent;
+import com.intellij.diff.requests.ContentDiffRequest;
+import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.requests.SimpleDiffRequest;
+import com.intellij.diff.tools.holders.EditorHolder;
+import com.intellij.diff.tools.holders.EditorHolderFactory;
+import com.intellij.diff.tools.util.DiffDataKeys;
+import com.intellij.diff.tools.util.FocusTrackerSupport.ThreesideFocusTrackerSupport;
+import com.intellij.diff.tools.util.SimpleDiffPanel;
+import com.intellij.diff.tools.util.base.ListenerDiffViewerBase;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.diff.util.ThreeSide;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.diff.DiffBundle;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.util.Disposer;
+import org.jetbrains.annotations.CalledInAwt;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class ThreesideDiffViewer<T extends EditorHolder> extends ListenerDiffViewerBase {
+ @NotNull protected final SimpleDiffPanel myPanel;
+ @NotNull protected final ThreesideContentPanel myContentPanel;
+
+ @NotNull private final List<T> myHolders;
+
+ @NotNull private final ThreesideFocusTrackerSupport myFocusTrackerSupport;
+
+ public ThreesideDiffViewer(@NotNull DiffContext context, @NotNull ContentDiffRequest request, @NotNull EditorHolderFactory<T> factory) {
+ super(context, request);
+
+ myHolders = createEditorHolders(factory);
+
+ List<JComponent> titlePanel = createTitles();
+ myFocusTrackerSupport = new ThreesideFocusTrackerSupport(myHolders);
+ myContentPanel = new ThreesideContentPanel(myHolders, titlePanel);
+
+ myPanel = new SimpleDiffPanel(myContentPanel, this, context);
+ }
+
+ @Override
+ @CalledInAwt
+ protected void onDispose() {
+ destroyEditorHolders();
+ super.onDispose();
+ }
+
+ @Override
+ @CalledInAwt
+ protected void processContextHints() {
+ super.processContextHints();
+ myFocusTrackerSupport.processContextHints(myRequest, myContext);
+ }
+
+ @Override
+ @CalledInAwt
+ protected void updateContextHints() {
+ super.updateContextHints();
+ myFocusTrackerSupport.updateContextHints(myRequest, myContext);
+ }
+
+ @NotNull
+ protected List<T> createEditorHolders(@NotNull EditorHolderFactory<T> factory) {
+ List<DiffContent> contents = myRequest.getContents();
+
+ List<T> holders = new ArrayList<T>(3);
+ for (int i = 0; i < 3; i++) {
+ DiffContent content = contents.get(i);
+ holders.add(factory.create(content, myContext));
+ }
+ return holders;
+ }
+
+ private void destroyEditorHolders() {
+ for (T holder : myHolders) {
+ Disposer.dispose(holder);
+ }
+ }
+
+ @NotNull
+ protected List<JComponent> createTitles() {
+ return DiffUtil.createSimpleTitles(myRequest);
+ }
+
+ //
+ // Getters
+ //
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myPanel;
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ if (!myPanel.isGoodContent()) return null;
+ return getCurrentEditorHolder().getPreferredFocusedComponent();
+ }
+
+ @NotNull
+ public ThreeSide getCurrentSide() {
+ return myFocusTrackerSupport.getCurrentSide();
+ }
+
+ protected void setCurrentSide(@NotNull ThreeSide side) {
+ myFocusTrackerSupport.setCurrentSide(side);
+ }
+
+ @NotNull
+ protected List<T> getEditorHolders() {
+ return myHolders;
+ }
+
+ @NotNull
+ protected T getCurrentEditorHolder() {
+ return getCurrentSide().select(getEditorHolders());
+ }
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) {
+ return DiffUtil.getVirtualFile(myRequest, getCurrentSide());
+ }
+ else if (DiffDataKeys.CURRENT_CONTENT.is(dataId)) {
+ return getCurrentSide().select(myRequest.getContents());
+ }
+ return super.getData(dataId);
+ }
+
+ //
+ // Misc
+ //
+
+ @Nullable
+ @Override
+ protected OpenFileDescriptor getOpenFileDescriptor() {
+ return getCurrentSide().select(getRequest().getContents()).getOpenFileDescriptor();
+ }
+
+ public static <T extends EditorHolder> boolean canShowRequest(@NotNull DiffContext context,
+ @NotNull DiffRequest request,
+ @NotNull EditorHolderFactory<T> factory) {
+ if (!(request instanceof ContentDiffRequest)) return false;
+
+ List<DiffContent> contents = ((ContentDiffRequest)request).getContents();
+ if (contents.size() != 3) return false;
+
+ boolean canShow = true;
+ boolean wantShow = false;
+ for (DiffContent content : contents) {
+ canShow &= factory.canShowContent(content, context);
+ wantShow |= factory.wantShowContent(content, context);
+ }
+ return canShow && wantShow;
+ }
+
+ //
+ // Actions
+ //
+
+ protected class ShowLeftBasePartialDiffAction extends ShowPartialDiffAction {
+ public ShowLeftBasePartialDiffAction() {
+ super(ThreeSide.LEFT, ThreeSide.BASE, DiffBundle.message("merge.partial.diff.action.name.0.1"), null, AllIcons.Diff.LeftDiff);
+ }
+ }
+
+ protected class ShowBaseRightPartialDiffAction extends ShowPartialDiffAction {
+ public ShowBaseRightPartialDiffAction() {
+ super(ThreeSide.BASE, ThreeSide.RIGHT, DiffBundle.message("merge.partial.diff.action.name.1.2"), null, AllIcons.Diff.RightDiff);
+ }
+ }
+
+ protected class ShowLeftRightPartialDiffAction extends ShowPartialDiffAction {
+ public ShowLeftRightPartialDiffAction() {
+ super(ThreeSide.LEFT, ThreeSide.RIGHT, DiffBundle.message("merge.partial.diff.action.name"), null, AllIcons.Diff.BranchDiff);
+ }
+ }
+
+ protected class ShowPartialDiffAction extends DumbAwareAction {
+ @NotNull private final ThreeSide mySide1;
+ @NotNull private final ThreeSide mySide2;
+
+ public ShowPartialDiffAction(@NotNull ThreeSide side1,
+ @NotNull ThreeSide side2,
+ @NotNull String text,
+ @Nullable String description,
+ @NotNull Icon icon) {
+ super(text, description, icon);
+ mySide1 = side1;
+ mySide2 = side2;
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ List<DiffContent> contents = myRequest.getContents();
+ List<String> titles = myRequest.getContentTitles();
+
+ DiffRequest request = new SimpleDiffRequest(myRequest.getTitle(),
+ mySide1.select(contents), mySide2.select(contents),
+ mySide1.select(titles), mySide2.select(titles));
+ DiffManager.getInstance().showDiff(myProject, request, new DiffDialogHints(null, myPanel));
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.util.side;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.actions.impl.OpenInEditorWithMouseAction;
+import com.intellij.diff.actions.impl.SetEditorSettingsAction;
+import com.intellij.diff.contents.DocumentContent;
+import com.intellij.diff.requests.ContentDiffRequest;
+import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.holders.EditorHolderFactory;
+import com.intellij.diff.tools.holders.TextEditorHolder;
+import com.intellij.diff.tools.util.DiffDataKeys;
+import com.intellij.diff.tools.util.SyncScrollSupport;
+import com.intellij.diff.tools.util.SyncScrollSupport.ThreesideSyncScrollSupport;
+import com.intellij.diff.tools.util.base.InitialScrollPositionSupport;
+import com.intellij.diff.tools.util.base.TextDiffSettingsHolder;
+import com.intellij.diff.tools.util.base.TextDiffViewerUtil;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.diff.util.Side;
+import com.intellij.diff.util.ThreeSide;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.LogicalPosition;
+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.editor.ex.EditorMarkupModel;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.CalledInAwt;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.List;
+
+public abstract class ThreesideTextDiffViewer extends ThreesideDiffViewer<TextEditorHolder> {
+ public static final Logger LOG = Logger.getInstance(ThreesideTextDiffViewer.class);
+
+ @Nullable private List<? extends EditorEx> myEditors;
+ @NotNull private final List<? extends EditorEx> myEditableEditors;
+
+ @NotNull private final MyVisibleAreaListener myVisibleAreaListener1 = new MyVisibleAreaListener(Side.LEFT);
+ @NotNull private final MyVisibleAreaListener myVisibleAreaListener2 = new MyVisibleAreaListener(Side.RIGHT);
+ @Nullable protected ThreesideSyncScrollSupport mySyncScrollSupport;
+
+ @NotNull protected final SetEditorSettingsAction myEditorSettingsAction;
+
+ public ThreesideTextDiffViewer(@NotNull DiffContext context, @NotNull ContentDiffRequest request) {
+ super(context, request, TextEditorHolder.TextEditorHolderFactory.INSTANCE);
+
+ //new MyFocusOppositePaneAction().setupAction(myPanel, this); // TODO
+
+ myEditorSettingsAction = new SetEditorSettingsAction(getTextSettings(), getEditors());
+ myEditorSettingsAction.applyDefaults();
+
+ new MyOpenInEditorWithMouseAction().register(getEditors());
+
+ myEditableEditors = TextDiffViewerUtil.getEditableEditors(getEditors());
+
+ TextDiffViewerUtil.checkDifferentDocuments(myRequest);
+ }
+
+ @Override
+ @CalledInAwt
+ protected void onInit() {
+ super.onInit();
+ installEditorListeners();
+ }
+
+ @Override
+ @CalledInAwt
+ protected void onDispose() {
+ destroyEditorListeners();
+ super.onDispose();
+ }
+
+ @NotNull
+ @Override
+ protected List<TextEditorHolder> createEditorHolders(@NotNull EditorHolderFactory<TextEditorHolder> factory) {
+ List<TextEditorHolder> holders = super.createEditorHolders(factory);
+
+ boolean[] forceReadOnly = TextDiffViewerUtil.checkForceReadOnly(myContext, myRequest);
+ for (int i = 0; i < 3; i++) {
+ if (forceReadOnly[i]) holders.get(i).getEditor().setViewer(true);
+ }
+
+ ThreeSide.LEFT.select(holders).getEditor().setVerticalScrollbarOrientation(EditorEx.VERTICAL_SCROLLBAR_LEFT);
+ ((EditorMarkupModel)ThreeSide.BASE.select(holders).getEditor().getMarkupModel()).setErrorStripeVisible(false);
+
+ if (Registry.is("diff.divider.repainting.disable.blitting")) {
+ for (TextEditorHolder holder : holders) {
+ holder.getEditor().getScrollPane().getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
+ }
+ }
+
+ return holders;
+ }
+
+ @NotNull
+ @Override
+ protected List<JComponent> createTitles() {
+ return DiffUtil.createTextTitles(myRequest, getEditors());
+ }
+
+ //
+ // Listeners
+ //
+
+ @CalledInAwt
+ protected void installEditorListeners() {
+ new TextDiffViewerUtil.EditorActionsPopup(createEditorPopupActions()).install(getEditors());
+
+ new TextDiffViewerUtil.EditorFontSizeSynchronizer(getEditors()).install(this);
+
+ getEditor(ThreeSide.LEFT).getScrollingModel().addVisibleAreaListener(myVisibleAreaListener1);
+ getEditor(ThreeSide.BASE).getScrollingModel().addVisibleAreaListener(myVisibleAreaListener1);
+
+ getEditor(ThreeSide.BASE).getScrollingModel().addVisibleAreaListener(myVisibleAreaListener2);
+ getEditor(ThreeSide.RIGHT).getScrollingModel().addVisibleAreaListener(myVisibleAreaListener2);
+
+ SyncScrollSupport.SyncScrollable scrollable1 = getSyncScrollable(Side.LEFT);
+ SyncScrollSupport.SyncScrollable scrollable2 = getSyncScrollable(Side.RIGHT);
+ if (scrollable1 != null && scrollable2 != null) {
+ mySyncScrollSupport = new ThreesideSyncScrollSupport(getEditors(), scrollable1, scrollable2);
+ }
+ }
+
+ @CalledInAwt
+ public void destroyEditorListeners() {
+ getEditor(ThreeSide.LEFT).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener1);
+ getEditor(ThreeSide.BASE).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener1);
+
+ getEditor(ThreeSide.BASE).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener2);
+ getEditor(ThreeSide.RIGHT).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener2);
+
+ mySyncScrollSupport = null;
+ }
+
+ protected void disableSyncScrollSupport(boolean disable) {
+ if (mySyncScrollSupport != null) {
+ mySyncScrollSupport.setDisabled(disable);
+ }
+ }
+
+ //
+ // Diff
+ //
+
+ @NotNull
+ public TextDiffSettingsHolder.TextDiffSettings getTextSettings() {
+ return TextDiffViewerUtil.getTextSettings(myContext);
+ }
+
+ @NotNull
+ protected List<AnAction> createEditorPopupActions() {
+ return TextDiffViewerUtil.createEditorPopupActions();
+ }
+
+ @Override
+ protected void onDocumentChange(@NotNull DocumentEvent event) {
+ super.onDocumentChange(event);
+ myContentPanel.repaintDividers();
+ }
+
+ //
+ // Getters
+ //
+
+ @NotNull
+ public EditorEx getCurrentEditor() {
+ return getEditor(getCurrentSide());
+ }
+
+ @NotNull
+ public DocumentContent getCurrentContent() {
+ return getContent(getCurrentSide());
+ }
+
+ @NotNull
+ protected List<? extends DocumentContent> getContents() {
+ //noinspection unchecked
+ return (List)myRequest.getContents();
+ }
+
+ @NotNull
+ public List<? extends EditorEx> getEditors() {
+ if (myEditors == null) {
+ myEditors = ContainerUtil.map(getEditorHolders(), new Function<TextEditorHolder, EditorEx>() {
+ @Override
+ public EditorEx fun(TextEditorHolder holder) {
+ return holder.getEditor();
+ }
+ });
+ }
+ return myEditors;
+ }
+
+ @NotNull
+ protected List<? extends EditorEx> getEditableEditors() {
+ return myEditableEditors;
+ }
+
+ @NotNull
+ public EditorEx getEditor(@NotNull ThreeSide side) {
+ return side.select(getEditors());
+ }
+
+ @NotNull
+ public DocumentContent getContent(@NotNull ThreeSide side) {
+ return side.select(getContents());
+ }
+
+ //
+ // Abstract
+ //
+
+ @CalledInAwt
+ protected void scrollToLine(@NotNull ThreeSide side, int line) {
+ DiffUtil.scrollEditor(getEditor(side), line, false);
+ setCurrentSide(side);
+ }
+
+ @Nullable
+ protected abstract SyncScrollSupport.SyncScrollable getSyncScrollable(@NotNull Side side);
+
+ //
+ // Misc
+ //
+
+ @Nullable
+ @Override
+ protected OpenFileDescriptor getOpenFileDescriptor() {
+ int offset = getCurrentEditor().getCaretModel().getOffset();
+ return getCurrentContent().getOpenFileDescriptor(offset);
+ }
+
+ public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ return ThreesideDiffViewer.canShowRequest(context, request, TextEditorHolder.TextEditorHolderFactory.INSTANCE);
+ }
+
+ //
+ // Actions
+ //
+
+ private class MyOpenInEditorWithMouseAction extends OpenInEditorWithMouseAction {
+ @Override
+ protected OpenFileDescriptor getDescriptor(@NotNull Editor editor, int line) {
+ ThreeSide side = null;
+ if (editor == getEditor(ThreeSide.LEFT)) side = ThreeSide.LEFT;
+ if (editor == getEditor(ThreeSide.RIGHT)) side = ThreeSide.RIGHT;
+ if (editor == getEditor(ThreeSide.BASE)) side = ThreeSide.BASE;
+ if (side == null) return null;
+
+ int offset = editor.logicalPositionToOffset(new LogicalPosition(line, 0));
+ return getContent(side).getOpenFileDescriptor(offset);
+ }
+ }
+
+ protected class MyToggleAutoScrollAction extends TextDiffViewerUtil.ToggleAutoScrollAction {
+ public MyToggleAutoScrollAction() {
+ super(getTextSettings());
+ }
+ }
+
+ //
+ // Helpers
+ //
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) {
+ return getCurrentEditor();
+ }
+ return super.getData(dataId);
+ }
+
+ private class MyVisibleAreaListener implements VisibleAreaListener {
+ @NotNull Side mySide;
+
+ public MyVisibleAreaListener(@NotNull Side side) {
+ mySide = side;
+ }
+
+ @Override
+ public void visibleAreaChanged(VisibleAreaEvent e) {
+ if (mySyncScrollSupport != null) mySyncScrollSupport.visibleAreaChanged(e);
+ if (Registry.is("diff.divider.repainting.fix")) {
+ myContentPanel.repaint();
+ }
+ else {
+ myContentPanel.repaintDivider(mySide);
+ }
+ }
+ }
+
+ protected abstract class MyInitialScrollPositionHelper extends InitialScrollPositionSupport.ThreesideInitialScrollHelper {
+ @NotNull
+ @Override
+ protected List<? extends Editor> getEditors() {
+ return ThreesideTextDiffViewer.this.getEditors();
+ }
+
+ @Override
+ protected void disableSyncScroll(boolean value) {
+ disableSyncScrollSupport(value);
+ }
+
+ @Override
+ protected boolean doScrollToLine() {
+ if (myScrollToLine == null) return false;
+
+ scrollToLine(myScrollToLine.first, myScrollToLine.second);
+ return true;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.util.side;
+
+import com.intellij.diff.tools.holders.EditorHolder;
+import com.intellij.diff.tools.util.DiffSplitter;
+import com.intellij.diff.util.Side;
+import org.jetbrains.annotations.CalledInAwt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.List;
+
+public class TwosideContentPanel extends JPanel {
+ @NotNull private final DiffSplitter mySplitter;
+
+ public TwosideContentPanel(@NotNull List<? extends EditorHolder> holders, @NotNull List<JComponent> titleComponents) {
+ super(new BorderLayout());
+ assert holders.size() == 2;
+ assert titleComponents.size() == 2;
+
+ mySplitter = new DiffSplitter();
+ mySplitter.setFirstComponent(new HolderPanel(Side.LEFT.select(holders), Side.LEFT.select(titleComponents)));
+ mySplitter.setSecondComponent(new HolderPanel(Side.RIGHT.select(holders), Side.RIGHT.select(titleComponents)));
+ mySplitter.setHonorComponentsMinimumSize(false);
+ add(mySplitter, BorderLayout.CENTER);
+ }
+
+ @CalledInAwt
+ public void setPainter(@Nullable DiffSplitter.Painter painter) {
+ mySplitter.setPainter(painter);
+ }
+
+ public void repaintDivider() {
+ mySplitter.repaintDivider();
+ }
+
+ @NotNull
+ public DiffSplitter getSplitter() {
+ return mySplitter;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.util.side;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.contents.DiffContent;
+import com.intellij.diff.requests.ContentDiffRequest;
+import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.holders.EditorHolder;
+import com.intellij.diff.tools.holders.EditorHolderFactory;
+import com.intellij.diff.tools.util.DiffDataKeys;
+import com.intellij.diff.tools.util.FocusTrackerSupport.TwosideFocusTrackerSupport;
+import com.intellij.diff.tools.util.SimpleDiffPanel;
+import com.intellij.diff.tools.util.base.ListenerDiffViewerBase;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.diff.util.Side;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.util.Disposer;
+import org.jetbrains.annotations.CalledInAwt;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class TwosideDiffViewer<T extends EditorHolder> extends ListenerDiffViewerBase {
+ @NotNull protected final SimpleDiffPanel myPanel;
+ @NotNull protected final TwosideContentPanel myContentPanel;
+
+ @NotNull private final List<T> myHolders;
+
+ @NotNull private final TwosideFocusTrackerSupport myFocusTrackerSupport;
+
+ public TwosideDiffViewer(@NotNull DiffContext context, @NotNull ContentDiffRequest request, @NotNull EditorHolderFactory<T> factory) {
+ super(context, request);
+
+ myHolders = createEditorHolders(factory);
+
+ List<JComponent> titlePanels = createTitles();
+ myFocusTrackerSupport = new TwosideFocusTrackerSupport(myHolders);
+ myContentPanel = new TwosideContentPanel(myHolders, titlePanels);
+
+ myPanel = new SimpleDiffPanel(myContentPanel, this, context);
+ }
+
+ @Override
+ @CalledInAwt
+ protected void onDispose() {
+ destroyEditorHolders();
+ super.onDispose();
+ }
+
+ @Override
+ @CalledInAwt
+ protected void processContextHints() {
+ super.processContextHints();
+ myFocusTrackerSupport.processContextHints(myRequest, myContext);
+ }
+
+ @Override
+ @CalledInAwt
+ protected void updateContextHints() {
+ super.updateContextHints();
+ myFocusTrackerSupport.updateContextHints(myRequest, myContext);
+ }
+
+ //
+ // Editors
+ //
+
+ @NotNull
+ protected List<T> createEditorHolders(@NotNull EditorHolderFactory<T> factory) {
+ List<DiffContent> contents = myRequest.getContents();
+
+ List<T> holders = new ArrayList<T>(2);
+ for (int i = 0; i < 2; i++) {
+ DiffContent content = contents.get(i);
+ holders.add(factory.create(content, myContext));
+ }
+ return holders;
+ }
+
+ private void destroyEditorHolders() {
+ for (T holder : myHolders) {
+ Disposer.dispose(holder);
+ }
+ }
+
+ @NotNull
+ protected List<JComponent> createTitles() {
+ return DiffUtil.createSimpleTitles(myRequest);
+ }
+
+ //
+ // Getters
+ //
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myPanel;
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ if (!myPanel.isGoodContent()) return null;
+ return getCurrentEditorHolder().getPreferredFocusedComponent();
+ }
+
+ @NotNull
+ public Side getCurrentSide() {
+ return myFocusTrackerSupport.getCurrentSide();
+ }
+
+ protected void setCurrentSide(@NotNull Side side) {
+ myFocusTrackerSupport.setCurrentSide(side);
+ }
+
+ @NotNull
+ protected List<T> getEditorHolders() {
+ return myHolders;
+ }
+
+ @NotNull
+ protected T getCurrentEditorHolder() {
+ return getCurrentSide().select(getEditorHolders());
+ }
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) {
+ return DiffUtil.getVirtualFile(myRequest, getCurrentSide());
+ }
+ else if (DiffDataKeys.CURRENT_CONTENT.is(dataId)) {
+ return getCurrentSide().select(myRequest.getContents());
+ }
+ return super.getData(dataId);
+ }
+
+ //
+ // Misc
+ //
+
+ @Nullable
+ @Override
+ protected OpenFileDescriptor getOpenFileDescriptor() {
+ return getCurrentSide().select(getRequest().getContents()).getOpenFileDescriptor();
+ }
+
+ public static <T extends EditorHolder> boolean canShowRequest(@NotNull DiffContext context,
+ @NotNull DiffRequest request,
+ @NotNull EditorHolderFactory<T> factory) {
+ if (!(request instanceof ContentDiffRequest)) return false;
+
+ List<DiffContent> contents = ((ContentDiffRequest)request).getContents();
+ if (contents.size() != 2) return false;
+
+ boolean canShow = true;
+ boolean wantShow = false;
+ for (DiffContent content : contents) {
+ canShow &= factory.canShowContent(content, context);
+ wantShow |= factory.wantShowContent(content, context);
+ }
+ return canShow && wantShow;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2015 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.diff.tools.util.side;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.actions.impl.FocusOppositePaneAction;
+import com.intellij.diff.actions.impl.OpenInEditorWithMouseAction;
+import com.intellij.diff.actions.impl.SetEditorSettingsAction;
+import com.intellij.diff.contents.DocumentContent;
+import com.intellij.diff.requests.ContentDiffRequest;
+import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.tools.holders.EditorHolderFactory;
+import com.intellij.diff.tools.holders.TextEditorHolder;
+import com.intellij.diff.tools.util.DiffDataKeys;
+import com.intellij.diff.tools.util.SyncScrollSupport;
+import com.intellij.diff.tools.util.SyncScrollSupport.TwosideSyncScrollSupport;
+import com.intellij.diff.tools.util.base.InitialScrollPositionSupport;
+import com.intellij.diff.tools.util.base.TextDiffSettingsHolder;
+import com.intellij.diff.tools.util.base.TextDiffViewerUtil;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.diff.util.Side;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.ScrollType;
+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.registry.Registry;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.CalledInAwt;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.List;
+
+public abstract class TwosideTextDiffViewer extends TwosideDiffViewer<TextEditorHolder> {
+ public static final Logger LOG = Logger.getInstance(TwosideTextDiffViewer.class);
+
+ @NotNull private final List<? extends EditorEx> myEditableEditors;
+ @Nullable private List<? extends EditorEx> myEditors;
+
+ @NotNull protected final SetEditorSettingsAction myEditorSettingsAction;
+
+ @NotNull private final MyVisibleAreaListener myVisibleAreaListener = new MyVisibleAreaListener();
+
+ @Nullable private TwosideSyncScrollSupport mySyncScrollSupport;
+
+ public TwosideTextDiffViewer(@NotNull DiffContext context, @NotNull ContentDiffRequest request) {
+ super(context, request, TextEditorHolder.TextEditorHolderFactory.INSTANCE);
+
+ new MyFocusOppositePaneAction(true).setupAction(myPanel);
+ new MyFocusOppositePaneAction(false).setupAction(myPanel);
+
+ myEditorSettingsAction = new SetEditorSettingsAction(getTextSettings(), getEditors());
+ myEditorSettingsAction.applyDefaults();
+
+ new MyOpenInEditorWithMouseAction().register(getEditors());
+
+ myEditableEditors = TextDiffViewerUtil.getEditableEditors(getEditors());
+
+ TextDiffViewerUtil.checkDifferentDocuments(myRequest);
+ }
+
+ @Override
+ @CalledInAwt
+ protected void onInit() {
+ super.onInit();
+ installEditorListeners();
+ }
+
+ @Override
+ @CalledInAwt
+ protected void onDispose() {
+ destroyEditorListeners();
+ super.onDispose();
+ }
+
+ @NotNull
+ @Override
+ protected List<TextEditorHolder> createEditorHolders(@NotNull EditorHolderFactory<TextEditorHolder> factory) {
+ List<TextEditorHolder> holders = super.createEditorHolders(factory);
+
+ boolean[] forceReadOnly = TextDiffViewerUtil.checkForceReadOnly(myContext, myRequest);
+ for (int i = 0; i < 2; i++) {
+ if (forceReadOnly[i]) holders.get(i).getEditor().setViewer(true);
+ }
+
+ Side.LEFT.select(holders).getEditor().setVerticalScrollbarOrientation(EditorEx.VERTICAL_SCROLLBAR_LEFT);
+
+ if (Registry.is("diff.divider.repainting.disable.blitting")) {
+ for (TextEditorHolder holder : holders) {
+ holder.getEditor().getScrollPane().getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
+ }
+ }
+
+ return holders;
+ }
+
+ @NotNull
+ @Override
+ protected List<JComponent> createTitles() {
+ return DiffUtil.createTextTitles(myRequest, getEditors());
+ }
+
+ //
+ // Diff
+ //
+
+ @NotNull
+ public TextDiffSettingsHolder.TextDiffSettings getTextSettings() {
+ return TextDiffViewerUtil.getTextSettings(myContext);
+ }
+
+ @NotNull
+ protected List<AnAction> createEditorPopupActions() {
+ return TextDiffViewerUtil.createEditorPopupActions();
+ }
+
+ @Override
+ protected void onDocumentChange(@NotNull DocumentEvent event) {
+ super.onDocumentChange(event);
+ myContentPanel.repaintDivider();
+ }
+
+ //
+ // Listeners
+ //
+
+ @CalledInAwt
+ protected void installEditorListeners() {
+ new TextDiffViewerUtil.EditorActionsPopup(createEditorPopupActions()).install(getEditors());
+
+ new TextDiffViewerUtil.EditorFontSizeSynchronizer(getEditors()).install(this);
+
+
+ getEditor(Side.LEFT).getScrollingModel().addVisibleAreaListener(myVisibleAreaListener);
+ getEditor(Side.RIGHT).getScrollingModel().addVisibleAreaListener(myVisibleAreaListener);
+
+ SyncScrollSupport.SyncScrollable scrollable = getSyncScrollable();
+ if (scrollable != null) {
+ mySyncScrollSupport = new TwosideSyncScrollSupport(getEditors(), scrollable);
+ }
+ }
+
+ @CalledInAwt
+ protected void destroyEditorListeners() {
+ getEditor(Side.LEFT).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener);
+ getEditor(Side.RIGHT).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener);
+
+ mySyncScrollSupport = null;
+ }
+
+ protected void disableSyncScrollSupport(boolean disable) {
+ if (mySyncScrollSupport != null) {
+ mySyncScrollSupport.setDisabled(disable);
+ }
+ }
+
+ //
+ // Getters
+ //
+
+
+ @NotNull
+ protected List<? extends DocumentContent> getContents() {
+ //noinspection unchecked
+ return (List)myRequest.getContents();
+ }
+
+ @NotNull
+ public List<? extends EditorEx> getEditors() {
+ if (myEditors == null) {
+ myEditors = ContainerUtil.map(getEditorHolders(), new Function<TextEditorHolder, EditorEx>() {
+ @Override
+ public EditorEx fun(TextEditorHolder holder) {
+ return holder.getEditor();
+ }
+ });
+ }
+ return myEditors;
+ }
+
+ @NotNull
+ protected List<? extends EditorEx> getEditableEditors() {
+ return myEditableEditors;
+ }
+
+ @NotNull
+ public EditorEx getCurrentEditor() {
+ return getEditor(getCurrentSide());
+ }
+
+ @NotNull
+ public DocumentContent getCurrentContent() {
+ return getContent(getCurrentSide());
+ }
+
+ @NotNull
+ public EditorEx getEditor1() {
+ return getEditor(Side.LEFT);
+ }
+
+ @NotNull
+ public EditorEx getEditor2() {
+ return getEditor(Side.RIGHT);
+ }
+
+
+ @NotNull
+ public EditorEx getEditor(@NotNull Side side) {
+ return side.select(getEditors());
+ }
+
+ @NotNull
+ public DocumentContent getContent(@NotNull Side side) {
+ return side.select(getContents());
+ }
+
+ @NotNull
+ public DocumentContent getContent1() {
+ return getContent(Side.LEFT);
+ }
+
+ @NotNull
+ public DocumentContent getContent2() {
+ return getContent(Side.RIGHT);
+ }
+
+ @Nullable
+ public TwosideSyncScrollSupport getSyncScrollSupport() {
+ return mySyncScrollSupport;
+ }
+
+ //
+ // Abstract
+ //
+
+ @CalledInAwt
+ @NotNull
+ protected LogicalPosition transferPosition(@NotNull Side baseSide, @NotNull LogicalPosition position) {
+ if (mySyncScrollSupport == null) return position;
+ int line = mySyncScrollSupport.getScrollable().transfer(baseSide, position.line);
+ return new LogicalPosition(line, position.column);
+ }
+
+ @CalledInAwt
+ protected void scrollToLine(@NotNull Side side, int line) {
+ DiffUtil.scrollEditor(getEditor(side), line, false);
+ setCurrentSide(side);
+ }
+
+ @Nullable
+ protected abstract SyncScrollSupport.SyncScrollable getSyncScrollable();
+
+ //
+ // Misc
+ //
+
+ @Nullable
+ @Override
+ protected OpenFileDescriptor getOpenFileDescriptor() {
+ int offset = getCurrentEditor().getCaretModel().getOffset();
+ return getCurrentContent().getOpenFileDescriptor(offset);
+ }
+
+ public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
+ return TwosideDiffViewer.canShowRequest(context, request, TextEditorHolder.TextEditorHolderFactory.INSTANCE);
+ }
+
+ //
+ // Actions
+ //
+
+ private class MyFocusOppositePaneAction extends FocusOppositePaneAction {
+ public MyFocusOppositePaneAction(boolean scrollToPosition) {
+ super(scrollToPosition);
+ }
+
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent e) {
+ Side currentSide = getCurrentSide();
+ Side targetSide = currentSide.other();
+
+ EditorEx currentEditor = getEditor(currentSide);
+ EditorEx targetEditor = getEditor(targetSide);
+
+ if (myScrollToPosition) {
+ LogicalPosition position = transferPosition(currentSide, currentEditor.getCaretModel().getLogicalPosition());
+ targetEditor.getCaretModel().moveToLogicalPosition(position);
+ }
+
+ setCurrentSide(targetSide);
+ myContext.requestFocus();
+ currentEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
+ }
+ }
+
+ private class MyOpenInEditorWithMouseAction extends OpenInEditorWithMouseAction {
+ @Override
+ protected OpenFileDescriptor getDescriptor(@NotNull Editor editor, int line) {
+ Side side = null;
+ if (editor == getEditor(Side.LEFT)) side = Side.LEFT;
+ if (editor == getEditor(Side.RIGHT)) side = Side.RIGHT;
+ if (side == null) return null;
+
+ int offset = editor.logicalPositionToOffset(new LogicalPosition(line, 0));
+ return getContent(side).getOpenFileDescriptor(offset);
+ }
+ }
+
+ protected class MyToggleAutoScrollAction extends TextDiffViewerUtil.ToggleAutoScrollAction {
+ public MyToggleAutoScrollAction() {
+ super(getTextSettings());
+ }
+ }
+
+ //
+ // Helpers
+ //
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) {
+ return getCurrentEditor();
+ }
+ return super.getData(dataId);
+ }
+
+ private class MyVisibleAreaListener implements VisibleAreaListener {
+ @Override
+ public void visibleAreaChanged(VisibleAreaEvent e) {
+ if (mySyncScrollSupport != null) mySyncScrollSupport.visibleAreaChanged(e);
+ if (Registry.is("diff.divider.repainting.fix")) {
+ myContentPanel.repaint();
+ }
+ else {
+ myContentPanel.repaintDivider();
+ }
+ }
+ }
+
+ protected abstract class MyInitialScrollPositionHelper extends InitialScrollPositionSupport.TwosideInitialScrollHelper {
+ @NotNull
+ @Override
+ protected List<? extends Editor> getEditors() {
+ return TwosideTextDiffViewer.this.getEditors();
+ }
+
+ @Override
+ protected void disableSyncScroll(boolean value) {
+ disableSyncScrollSupport(value);
+ }
+
+ @Override
+ protected boolean doScrollToLine() {
+ if (myScrollToLine == null) return false;
+
+ scrollToLine(myScrollToLine.first, myScrollToLine.second);
+ return true;
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright 2000-2015 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.diff.tools.util.threeside;
-
-import com.intellij.diff.util.Side;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.ex.EditorEx;
-import com.intellij.util.ui.ButtonlessScrollBarUI;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.util.ArrayList;
-import java.util.List;
-
-public class ThreesideTextContentPanel extends ThreesideContentPanel {
- @NotNull private final List<? extends Editor> myEditors;
-
- public ThreesideTextContentPanel(@NotNull List<? extends Editor> editors,
- @NotNull List<JComponent> titleComponents) {
- super(getComponents(editors), titleComponents);
- myEditors = editors;
- }
-
- @NotNull
- private static List<JComponent> getComponents(@NotNull List<? extends Editor> editors) {
- List<JComponent> result = new ArrayList<JComponent>();
-
- for (Editor editor : editors) {
- result.add(editor != null ? editor.getComponent() : null);
- }
- return result;
- }
-
- public void setScrollbarPainter(@NotNull ButtonlessScrollBarUI.ScrollbarRepaintCallback painter) {
- ((EditorEx)myEditors.get(1)).registerScrollBarRepaintCallback(painter);
- }
-
- @Override
- public void repaintDivider(@NotNull Side side) {
- super.repaintDivider(side);
- if (side == Side.RIGHT) ((EditorEx)myEditors.get(1)).getScrollPane().getVerticalScrollBar().repaint();
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2015 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.diff.tools.util.threeside;
-
-import com.intellij.diff.DiffContext;
-import com.intellij.diff.DiffDialogHints;
-import com.intellij.diff.DiffManager;
-import com.intellij.diff.contents.DiffContent;
-import com.intellij.diff.contents.DocumentContent;
-import com.intellij.diff.requests.ContentDiffRequest;
-import com.intellij.diff.requests.DiffRequest;
-import com.intellij.diff.requests.SimpleDiffRequest;
-import com.intellij.diff.tools.util.DiffDataKeys;
-import com.intellij.diff.tools.util.FocusTrackerSupport.ThreesideFocusTrackerSupport;
-import com.intellij.diff.tools.util.SimpleDiffPanel;
-import com.intellij.diff.tools.util.SyncScrollSupport;
-import com.intellij.diff.tools.util.SyncScrollSupport.ThreesideSyncScrollSupport;
-import com.intellij.diff.tools.util.base.InitialScrollPositionSupport;
-import com.intellij.diff.tools.util.base.TextDiffViewerBase;
-import com.intellij.diff.util.DiffUtil;
-import com.intellij.diff.util.Side;
-import com.intellij.diff.util.ThreeSide;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.diff.DiffBundle;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.EditorFactory;
-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.editor.ex.EditorMarkupModel;
-import com.intellij.openapi.fileEditor.OpenFileDescriptor;
-import com.intellij.openapi.project.DumbAwareAction;
-import com.intellij.openapi.util.registry.Registry;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.CalledInAwt;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
- public static final Logger LOG = Logger.getInstance(ThreesideTextDiffViewer.class);
-
- @NotNull private final EditorFactory myEditorFactory = EditorFactory.getInstance();
-
- @NotNull protected final SimpleDiffPanel myPanel;
- @NotNull protected final ThreesideTextContentPanel myContentPanel;
-
- @NotNull private final List<EditorEx> myEditors;
- @NotNull private final List<DocumentContent> myActualContents;
-
- @NotNull private final MyVisibleAreaListener myVisibleAreaListener1 = new MyVisibleAreaListener(Side.LEFT);
- @NotNull private final MyVisibleAreaListener myVisibleAreaListener2 = new MyVisibleAreaListener(Side.RIGHT);
-
- @NotNull protected final MySetEditorSettingsAction myEditorSettingsAction;
-
- @NotNull private final ThreesideFocusTrackerSupport myFocusTrackerSupport;
-
- @Nullable private ThreesideSyncScrollSupport mySyncScrollSupport;
-
- public ThreesideTextDiffViewer(@NotNull DiffContext context, @NotNull ContentDiffRequest request) {
- super(context, request);
-
- List<DiffContent> contents = myRequest.getContents();
- myActualContents = ContainerUtil.newArrayList((DocumentContent)contents.get(0),
- (DocumentContent)contents.get(1),
- (DocumentContent)contents.get(2));
-
-
- myEditors = createEditors();
- List<JComponent> titlePanel = DiffUtil.createTextTitles(myRequest, getEditors());
-
- myFocusTrackerSupport = new ThreesideFocusTrackerSupport(getEditors());
- myContentPanel = new ThreesideTextContentPanel(getEditors(), titlePanel);
-
- myPanel = new SimpleDiffPanel(myContentPanel, this, context);
-
-
- //new MyFocusOppositePaneAction().setupAction(myPanel, this); // TODO
-
- myEditorSettingsAction = new MySetEditorSettingsAction();
- myEditorSettingsAction.applyDefaults();
- }
-
- @Override
- @CalledInAwt
- protected void onDispose() {
- super.onDispose();
- destroyEditors();
- }
-
- @Override
- @CalledInAwt
- protected void processContextHints() {
- super.processContextHints();
- myFocusTrackerSupport.processContextHints(myRequest, myContext);
- }
-
- @Override
- @CalledInAwt
- protected void updateContextHints() {
- super.updateContextHints();
- myFocusTrackerSupport.updateContextHints(myRequest, myContext);
- }
-
- @NotNull
- protected List<EditorEx> createEditors() {
- boolean[] forceReadOnly = checkForceReadOnly();
- List<EditorEx> editors = new ArrayList<EditorEx>(3);
-
- for (int i = 0; i < getActualContents().size(); i++) {
- DocumentContent content = getActualContents().get(i);
- EditorEx editor = DiffUtil.createEditor(content.getDocument(), myProject, forceReadOnly[i], true);
- DiffUtil.configureEditor(editor, content, myProject);
- editors.add(editor);
-
- if (Registry.is("diff.divider.repainting.disable.blitting")) {
- editor.getScrollPane().getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
- }
- }
-
- editors.get(0).setVerticalScrollbarOrientation(EditorEx.VERTICAL_SCROLLBAR_LEFT);
- ((EditorMarkupModel)editors.get(1).getMarkupModel()).setErrorStripeVisible(false);
-
- return editors;
- }
-
- private void destroyEditors() {
- for (EditorEx editor : getEditors()) {
- myEditorFactory.releaseEditor(editor);
- }
- }
-
- //
- // Listeners
- //
-
- @CalledInAwt
- @Override
- protected void installEditorListeners() {
- super.installEditorListeners();
-
- getEditor(ThreeSide.LEFT).getScrollingModel().addVisibleAreaListener(myVisibleAreaListener1);
- getEditor(ThreeSide.BASE).getScrollingModel().addVisibleAreaListener(myVisibleAreaListener1);
-
- getEditor(ThreeSide.BASE).getScrollingModel().addVisibleAreaListener(myVisibleAreaListener2);
- getEditor(ThreeSide.RIGHT).getScrollingModel().addVisibleAreaListener(myVisibleAreaListener2);
-
- SyncScrollSupport.SyncScrollable scrollable1 = getSyncScrollable(Side.LEFT);
- SyncScrollSupport.SyncScrollable scrollable2 = getSyncScrollable(Side.RIGHT);
- if (scrollable1 != null && scrollable2 != null) {
- mySyncScrollSupport = new ThreesideSyncScrollSupport(getEditors(), scrollable1, scrollable2);
- }
- }
-
- @CalledInAwt
- @Override
- public void destroyEditorListeners() {
- super.destroyEditorListeners();
-
- getEditor(ThreeSide.LEFT).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener1);
- getEditor(ThreeSide.BASE).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener1);
-
- getEditor(ThreeSide.BASE).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener2);
- getEditor(ThreeSide.RIGHT).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener2);
-
- mySyncScrollSupport = null;
- }
-
- protected void disableSyncScrollSupport(boolean disable) {
- if (mySyncScrollSupport != null) {
- mySyncScrollSupport.setDisabled(disable);
- }
- }
-
- //
- // Diff
- //
-
- @Override
- protected void onDocumentChange(@NotNull DocumentEvent event) {
- super.onDocumentChange(event);
-
- myContentPanel.repaintDividers();
- }
-
- //
- // Getters
- //
-
- @NotNull
- @Override
- public JComponent getComponent() {
- return myPanel;
- }
-
- @Nullable
- @Override
- public JComponent getPreferredFocusedComponent() {
- return getCurrentEditor().getContentComponent();
- }
-
- @NotNull
- public EditorEx getCurrentEditor() {
- return getEditor(getCurrentSide());
- }
-
- @NotNull
- public DocumentContent getCurrentContent() {
- return getCurrentSide().select(getActualContents());
- }
-
- @NotNull
- @Override
- protected List<? extends EditorEx> getEditors() {
- return myEditors;
- }
-
- @NotNull
- protected EditorEx getEditor(@NotNull ThreeSide side) {
- return side.select(myEditors);
- }
-
- @NotNull
- public List<DocumentContent> getActualContents() {
- return myActualContents;
- }
-
- @NotNull
- public ThreeSide getCurrentSide() {
- return myFocusTrackerSupport.getCurrentSide();
- }
-
- public void setCurrentSide(@NotNull ThreeSide side) {
- myFocusTrackerSupport.setCurrentSide(side);
- }
-
- //
- // Abstract
- //
-
- @CalledInAwt
- protected void scrollToLine(@NotNull ThreeSide side, int line) {
- Editor editor = getEditor(side);
- DiffUtil.scrollEditor(editor, line, false);
- setCurrentSide(side);
- }
-
- @Nullable
- protected abstract SyncScrollSupport.SyncScrollable getSyncScrollable(@NotNull Side side);
-
- //
- // Misc
- //
-
- @Nullable
- @Override
- protected OpenFileDescriptor getOpenFileDescriptor() {
- EditorEx editor = getCurrentEditor();
-
- int offset = editor.getCaretModel().getOffset();
- return getCurrentContent().getOpenFileDescriptor(offset);
- }
-
- public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
- if (!(request instanceof ContentDiffRequest)) return false;
-
- List<DiffContent> contents = ((ContentDiffRequest)request).getContents();
- if (contents.size() != 3) return false;
-
- boolean canShow = true;
- boolean wantShow = false;
- for (DiffContent content : contents) {
- canShow &= canShowContent(content);
- wantShow |= wantShowContent(content);
- }
- return canShow && wantShow;
- }
-
- public static boolean canShowContent(@NotNull DiffContent content) {
- if (content instanceof DocumentContent) return true;
- return false;
- }
-
- public static boolean wantShowContent(@NotNull DiffContent content) {
- if (content instanceof DocumentContent) return true;
- return false;
- }
-
- //
- // Actions
- //
-
- protected class ShowLeftBasePartialDiffAction extends ShowPartialDiffAction {
- public ShowLeftBasePartialDiffAction() {
- super(ThreeSide.LEFT, ThreeSide.BASE, DiffBundle.message("merge.partial.diff.action.name.0.1"), null, AllIcons.Diff.LeftDiff);
- }
- }
-
- protected class ShowBaseRightPartialDiffAction extends ShowPartialDiffAction {
- public ShowBaseRightPartialDiffAction() {
- super(ThreeSide.BASE, ThreeSide.RIGHT, DiffBundle.message("merge.partial.diff.action.name.1.2"), null, AllIcons.Diff.RightDiff);
- }
- }
-
- protected class ShowLeftRightPartialDiffAction extends ShowPartialDiffAction {
- public ShowLeftRightPartialDiffAction() {
- super(ThreeSide.LEFT, ThreeSide.RIGHT, DiffBundle.message("merge.partial.diff.action.name"), null, AllIcons.Diff.BranchDiff);
- }
- }
-
- protected class ShowPartialDiffAction extends DumbAwareAction {
- @NotNull private final ThreeSide mySide1;
- @NotNull private final ThreeSide mySide2;
-
- public ShowPartialDiffAction(@NotNull ThreeSide side1, @NotNull ThreeSide side2,
- @NotNull String text, @Nullable String description, @NotNull Icon icon) {
- super(text, description, icon);
- mySide1 = side1;
- mySide2 = side2;
- }
-
- @Override
- public void actionPerformed(AnActionEvent e) {
- List<DiffContent> contents = myRequest.getContents();
- List<String> titles = myRequest.getContentTitles();
-
- DiffRequest request = new SimpleDiffRequest(myRequest.getTitle(),
- mySide1.select(contents), mySide2.select(contents),
- mySide1.select(titles), mySide2.select(titles));
- DiffManager.getInstance().showDiff(myProject, request, new DiffDialogHints(null, myPanel));
- }
- }
-
- //
- // Helpers
- //
-
- @Nullable
- @Override
- public Object getData(@NonNls String dataId) {
- if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) {
- return getCurrentEditor();
- }
- else if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) {
- return DiffUtil.getVirtualFile(myRequest, getCurrentSide());
- }
- else if (DiffDataKeys.CURRENT_CONTENT.is(dataId)) {
- return getCurrentContent();
- }
- return super.getData(dataId);
- }
-
- private class MyVisibleAreaListener implements VisibleAreaListener {
- @NotNull Side mySide;
-
- public MyVisibleAreaListener(@NotNull Side side) {
- mySide = side;
- }
-
- @Override
- public void visibleAreaChanged(VisibleAreaEvent e) {
- if (mySyncScrollSupport != null) mySyncScrollSupport.visibleAreaChanged(e);
- if (Registry.is("diff.divider.repainting.fix")) {
- myContentPanel.repaint();
- }
- else {
- myContentPanel.repaintDivider(mySide);
- }
- }
- }
-
- protected abstract class MyInitialScrollPositionHelper extends InitialScrollPositionSupport.ThreesideInitialScrollHelper {
- @NotNull
- @Override
- protected List<? extends Editor> getEditors() {
- return ThreesideTextDiffViewer.this.getEditors();
- }
-
- @Override
- protected void disableSyncScroll(boolean value) {
- disableSyncScrollSupport(value);
- }
-
- @Override
- protected boolean doScrollToLine() {
- if (myScrollToLine == null) return false;
- ThreeSide side = myScrollToLine.first;
- Integer line = myScrollToLine.second;
- if (getEditor(side) == null) return false;
-
- scrollToLine(side, line);
- return true;
- }
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2015 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.diff.tools.util.twoside;
-
-import com.intellij.diff.tools.util.DiffSplitter;
-import org.jetbrains.annotations.CalledInAwt;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.List;
-
-public class TwosideContentPanel extends JPanel {
- @Nullable private final DiffSplitter mySplitter;
-
- public TwosideContentPanel(@NotNull List<JComponent> titleComponents,
- @Nullable JComponent editor1,
- @Nullable JComponent editor2) {
- super(new BorderLayout());
- assert titleComponents.size() == 2;
-
- if (editor1 != null && editor2 != null) {
- mySplitter = new DiffSplitter();
- mySplitter.setFirstComponent(new MyPanel(editor1, titleComponents.get(0)));
- mySplitter.setSecondComponent(new MyPanel(editor2, titleComponents.get(1)));
- mySplitter.setHonorComponentsMinimumSize(false);
- add(mySplitter, BorderLayout.CENTER);
- }
- else {
- mySplitter = null;
- if (editor1 != null) {
- add(new MyPanel(editor1, titleComponents.get(0)), BorderLayout.CENTER);
- }
- else if (editor2 != null) {
- add(new MyPanel(editor2, titleComponents.get(1)), BorderLayout.CENTER);
- }
- }
- }
-
- @CalledInAwt
- public void setPainter(@Nullable DiffSplitter.Painter painter) {
- if (mySplitter != null) mySplitter.setPainter(painter);
- }
-
- public void repaintDivider() {
- if (mySplitter != null) mySplitter.repaintDivider();
- }
-
- @Nullable
- public DiffSplitter getSplitter() {
- return mySplitter;
- }
-
- private static class MyPanel extends JPanel {
- public MyPanel(@NotNull JComponent editor, @Nullable JComponent title) {
- super(new BorderLayout());
- add(editor, BorderLayout.CENTER);
- if (title != null) add(title, BorderLayout.NORTH);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2015 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.diff.tools.util.twoside;
-
-import com.intellij.diff.DiffContext;
-import com.intellij.diff.actions.impl.FocusOppositePaneAction;
-import com.intellij.diff.actions.impl.OpenInEditorWithMouseAction;
-import com.intellij.diff.contents.DiffContent;
-import com.intellij.diff.contents.DocumentContent;
-import com.intellij.diff.contents.EmptyContent;
-import com.intellij.diff.requests.ContentDiffRequest;
-import com.intellij.diff.requests.DiffRequest;
-import com.intellij.diff.tools.util.DiffDataKeys;
-import com.intellij.diff.tools.util.FocusTrackerSupport.TwosideFocusTrackerSupport;
-import com.intellij.diff.tools.util.SimpleDiffPanel;
-import com.intellij.diff.tools.util.SyncScrollSupport;
-import com.intellij.diff.tools.util.SyncScrollSupport.TwosideSyncScrollSupport;
-import com.intellij.diff.tools.util.base.InitialScrollPositionSupport;
-import com.intellij.diff.tools.util.base.TextDiffViewerBase;
-import com.intellij.diff.util.DiffUtil;
-import com.intellij.diff.util.Side;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.diagnostic.Logger;
-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.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.registry.Registry;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.CalledInAwt;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.util.List;
-
-public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
- public static final Logger LOG = Logger.getInstance(TwosideTextDiffViewer.class);
-
- @NotNull private final EditorFactory myEditorFactory = EditorFactory.getInstance();
-
- @NotNull protected final SimpleDiffPanel myPanel;
- @NotNull protected final TwosideTextContentPanel myContentPanel;
-
- @Nullable private final EditorEx myEditor1;
- @Nullable private final EditorEx myEditor2;
-
- @Nullable private final DocumentContent myActualContent1;
- @Nullable private final DocumentContent myActualContent2;
-
- @NotNull protected final MySetEditorSettingsAction myEditorSettingsAction;
-
- @NotNull private final MyVisibleAreaListener myVisibleAreaListener = new MyVisibleAreaListener();
-
- @NotNull private final TwosideFocusTrackerSupport myFocusTrackerSupport;
-
- @Nullable protected TwosideSyncScrollSupport mySyncScrollSupport;
-
- public TwosideTextDiffViewer(@NotNull DiffContext context, @NotNull ContentDiffRequest request) {
- super(context, request);
-
- List<DiffContent> contents = myRequest.getContents();
- myActualContent1 = contents.get(0) instanceof DocumentContent ? ((DocumentContent)contents.get(0)) : null;
- myActualContent2 = contents.get(1) instanceof DocumentContent ? ((DocumentContent)contents.get(1)) : null;
- assert myActualContent1 != null || myActualContent2 != null;
-
-
- List<EditorEx> editors = createEditors();
- List<JComponent> titlePanel = DiffUtil.createTextTitles(myRequest, editors);
-
- myEditor1 = editors.get(0);
- myEditor2 = editors.get(1);
- assert myEditor1 != null || myEditor2 != null;
-
- myFocusTrackerSupport = new TwosideFocusTrackerSupport(getEditor1(), getEditor2());
- myContentPanel = new TwosideTextContentPanel(titlePanel, getEditor1(), getEditor2());
-
- myPanel = new SimpleDiffPanel(myContentPanel, this, context);
-
-
- new MyFocusOppositePaneAction(true).setupAction(myPanel);
- new MyFocusOppositePaneAction(false).setupAction(myPanel);
-
- myEditorSettingsAction = new MySetEditorSettingsAction();
- myEditorSettingsAction.applyDefaults();
-
- new MyOpenInEditorWithMouseAction().register(getEditors());
- }
-
- @Override
- @CalledInAwt
- protected void onDispose() {
- super.onDispose();
- destroyEditors();
- }
-
- @Override
- @CalledInAwt
- protected void processContextHints() {
- super.processContextHints();
- myFocusTrackerSupport.processContextHints(myRequest, myContext);
- }
-
- @Override
- @CalledInAwt
- protected void updateContextHints() {
- super.updateContextHints();
- myFocusTrackerSupport.updateContextHints(myRequest, myContext);
- }
-
- @NotNull
- protected List<EditorEx> createEditors() {
- boolean[] forceReadOnly = checkForceReadOnly();
-
- // TODO: we may want to set editor highlighter in init() to speedup editor initialization
- EditorEx editor1 = null;
- EditorEx editor2 = null;
- if (getActualContent1() != null) {
- editor1 = DiffUtil.createEditor(getActualContent1().getDocument(), myProject, forceReadOnly[0], true);
- DiffUtil.configureEditor(editor1, getActualContent1(), myProject);
- }
- if (getActualContent2() != null) {
- editor2 = DiffUtil.createEditor(getActualContent2().getDocument(), myProject, forceReadOnly[1], true);
- DiffUtil.configureEditor(editor2, getActualContent2(), myProject);
- }
- if (editor1 != null && editor2 != null) {
- editor1.setVerticalScrollbarOrientation(EditorEx.VERTICAL_SCROLLBAR_LEFT);
- }
- if (Registry.is("diff.divider.repainting.disable.blitting")) {
- if (editor1 != null) editor1.getScrollPane().getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
- if (editor2 != null) editor2.getScrollPane().getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
- }
-
- return ContainerUtil.newArrayList(editor1, editor2);
- }
-
- //
- // Diff
- //
-
- @Override
- protected void onDocumentChange(@NotNull DocumentEvent event) {
- super.onDocumentChange(event);
- myContentPanel.repaintDivider();
- }
-
- //
- // Listeners
- //
-
- private void destroyEditors() {
- if (getEditor1() != null) myEditorFactory.releaseEditor(getEditor1());
- if (getEditor2() != null) myEditorFactory.releaseEditor(getEditor2());
- }
-
- @CalledInAwt
- @Override
- protected void installEditorListeners() {
- super.installEditorListeners();
- if (getEditor1() != null) {
- getEditor1().getScrollingModel().addVisibleAreaListener(myVisibleAreaListener);
- }
- if (getEditor2() != null) {
- getEditor2().getScrollingModel().addVisibleAreaListener(myVisibleAreaListener);
- }
- if (getEditor1() != null && getEditor2() != null) {
- SyncScrollSupport.SyncScrollable scrollable = getSyncScrollable();
- if (scrollable != null) {
- mySyncScrollSupport = new TwosideSyncScrollSupport(getEditor1(), getEditor2(), scrollable);
- }
- }
- }
-
- @CalledInAwt
- @Override
- protected void destroyEditorListeners() {
- super.destroyEditorListeners();
- if (getEditor1() != null) {
- getEditor1().getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener);
- }
- if (getEditor2() != null) {
- getEditor2().getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener);
- }
- mySyncScrollSupport = null;
- }
-
- protected void disableSyncScrollSupport(boolean disable) {
- if (mySyncScrollSupport != null) {
- mySyncScrollSupport.setDisabled(disable);
- }
- }
-
- //
- // Getters
- //
-
- @NotNull
- @Override
- protected List<? extends EditorEx> getEditors() {
- return ContainerUtil.list(getEditor1(), getEditor2());
- }
-
- @NotNull
- @Override
- public JComponent getComponent() {
- return myPanel;
- }
-
- @Nullable
- @Override
- public JComponent getPreferredFocusedComponent() {
- return getCurrentEditor().getContentComponent();
- }
-
- @NotNull
- public Side getCurrentSide() {
- return myFocusTrackerSupport.getCurrentSide();
- }
-
- public void setCurrentSide(@NotNull Side side) {
- myFocusTrackerSupport.setCurrentSide(side);
- }
-
- @NotNull
- public EditorEx getCurrentEditor() {
- //noinspection ConstantConditions
- return getEditor(getCurrentSide());
- }
-
- @NotNull
- public DocumentContent getCurrentContent() {
- //noinspection ConstantConditions
- return getActualContent(getCurrentSide());
- }
-
- @Nullable
- protected EditorEx getEditor1() {
- return myEditor1;
- }
-
- @Nullable
- protected EditorEx getEditor2() {
- return myEditor2;
- }
-
- @Nullable
- protected EditorEx getEditor(@NotNull Side side) {
- return side.select(myEditor1, myEditor2);
- }
-
- @Nullable
- public DocumentContent getActualContent1() {
- return myActualContent1;
- }
-
- @Nullable
- public DocumentContent getActualContent2() {
- return myActualContent2;
- }
-
- @Nullable
- protected DocumentContent getActualContent(@NotNull Side side) {
- return side.select(myActualContent1, myActualContent2);
- }
-
- //
- // Abstract
- //
-
- @CalledInAwt
- @NotNull
- protected LogicalPosition transferPosition(@NotNull Side baseSide, @NotNull LogicalPosition position) {
- if (mySyncScrollSupport == null) return position;
- int line = mySyncScrollSupport.getScrollable().transfer(baseSide, position.line);
- return new LogicalPosition(line, position.column);
- }
-
- @CalledInAwt
- protected void scrollToLine(@NotNull Side side, int line) {
- Editor editor = getEditor(side);
- if (editor == null) return;
- DiffUtil.scrollEditor(editor, line, false);
- setCurrentSide(side);
- }
-
- @Nullable
- protected abstract SyncScrollSupport.SyncScrollable getSyncScrollable();
-
- //
- // Misc
- //
-
- @Nullable
- @Override
- protected OpenFileDescriptor getOpenFileDescriptor() {
- EditorEx editor = getCurrentEditor();
-
- int offset = editor.getCaretModel().getOffset();
- return getCurrentContent().getOpenFileDescriptor(offset);
- }
-
- public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
- if (!(request instanceof ContentDiffRequest)) return false;
-
- List<DiffContent> contents = ((ContentDiffRequest)request).getContents();
- if (contents.size() != 2) return false;
-
- boolean canShow = true;
- boolean wantShow = false;
- for (DiffContent content : contents) {
- canShow &= canShowContent(content);
- wantShow |= wantShowContent(content);
- }
- return canShow && wantShow;
- }
-
- public static boolean canShowContent(@NotNull DiffContent content) {
- if (content instanceof EmptyContent) return true;
- if (content instanceof DocumentContent) return true;
- return false;
- }
-
- public static boolean wantShowContent(@NotNull DiffContent content) {
- if (content instanceof DocumentContent) return true;
- return false;
- }
-
- //
- // Actions
- //
-
- private class MyFocusOppositePaneAction extends FocusOppositePaneAction {
- public MyFocusOppositePaneAction(boolean scrollToPosition) {
- super(scrollToPosition);
- }
-
- @Override
- public void actionPerformed(@NotNull AnActionEvent e) {
- if (getEditor1() == null || getEditor2() == null) return;
-
- if (myScrollToPosition) {
- EditorEx currentEditor = getCurrentSide().select(getEditor1(), getEditor2());
- EditorEx targetEditor = getCurrentSide().other().select(getEditor1(), getEditor2());
- LogicalPosition position = transferPosition(getCurrentSide(), currentEditor.getCaretModel().getLogicalPosition());
- targetEditor.getCaretModel().moveToLogicalPosition(position);
- }
-
- setCurrentSide(getCurrentSide().other());
- myContext.requestFocus();
- getCurrentEditor().getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
- }
- }
-
- private class MyOpenInEditorWithMouseAction extends OpenInEditorWithMouseAction {
- @Override
- protected OpenFileDescriptor getDescriptor(@NotNull Editor editor, int line) {
- if (editor != getEditor1() && editor != getEditor2()) return null;
- Side side = Side.fromLeft(editor == getEditor1());
-
- DocumentContent content = getActualContent(side);
- if (content == null) return null;
-
- int offset = editor.logicalPositionToOffset(new LogicalPosition(line, 0));
-
- return content.getOpenFileDescriptor(offset);
- }
- }
-
- //
- // Helpers
- //
-
- @Nullable
- @Override
- public Object getData(@NonNls String dataId) {
- if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) {
- return getCurrentEditor();
- }
- else if (DiffDataKeys.CURRENT_CONTENT.is(dataId)) {
- return getCurrentContent();
- }
- else if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) {
- return DiffUtil.getVirtualFile(myRequest, getCurrentSide());
- }
-
- return super.getData(dataId);
- }
-
- private class MyVisibleAreaListener implements VisibleAreaListener {
- @Override
- public void visibleAreaChanged(VisibleAreaEvent e) {
- if (mySyncScrollSupport != null) mySyncScrollSupport.visibleAreaChanged(e);
- if (Registry.is("diff.divider.repainting.fix")) {
- myContentPanel.repaint();
- }
- else {
- myContentPanel.repaintDivider();
- }
- }
- }
-
- protected abstract class MyInitialScrollPositionHelper extends InitialScrollPositionSupport.TwosideInitialScrollHelper {
- @NotNull
- @Override
- protected List<? extends Editor> getEditors() {
- return TwosideTextDiffViewer.this.getEditors();
- }
-
- @Override
- protected void disableSyncScroll(boolean value) {
- disableSyncScrollSupport(value);
- }
-
- @Override
- protected boolean doScrollToLine() {
- if (myScrollToLine == null) return false;
- Side side = myScrollToLine.first;
- Integer line = myScrollToLine.second;
- if (getEditor(side) == null) return false;
-
- scrollToLine(side, line);
- return true;
- }
- }
-}
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.EditorMarkupModel;
import com.intellij.openapi.editor.ex.util.EmptyEditorHighlighter;
return Math.max(document.getLineCount(), 1);
}
+ //
+ // Updating ranges on change
+ //
+
+ public static int countLinesShift(@NotNull DocumentEvent e) {
+ return StringUtil.countNewLines(e.getNewFragment()) - StringUtil.countNewLines(e.getOldFragment());
+ }
+
+ @NotNull
+ public static UpdatedLineRange updateRangeOnModification(int start, int end, int changeStart, int changeEnd, int shift) {
+ return updateRangeOnModification(start, end, changeStart, changeEnd, shift, false);
+ }
+
+ @NotNull
+ public static UpdatedLineRange updateRangeOnModification(int start, int end, int changeStart, int changeEnd, int shift, boolean greedy) {
+ if (end <= changeStart) { // change before
+ return new UpdatedLineRange(start, end, false);
+ }
+ if (start >= changeEnd) { // change after
+ return new UpdatedLineRange(start + shift, end + shift, false);
+ }
+
+ if (start <= changeStart && end >= changeEnd) { // change inside
+ return new UpdatedLineRange(start, end + shift, false);
+ }
+
+ // range is damaged. We don't know new boundaries.
+ // But we can try to return approximate new position
+ int newChangeEnd = changeEnd + shift;
+
+ if (start >= changeStart && end <= changeEnd) { // fully inside change
+ return greedy ? new UpdatedLineRange(changeStart, newChangeEnd, true) :
+ new UpdatedLineRange(newChangeEnd, newChangeEnd, true);
+ }
+
+ if (start < changeStart) { // bottom boundary damaged
+ return greedy ? new UpdatedLineRange(start, newChangeEnd, true) :
+ new UpdatedLineRange(start, changeStart, true);
+ } else { // top boundary damaged
+ return greedy ? new UpdatedLineRange(changeStart, end + shift, true) :
+ new UpdatedLineRange(newChangeEnd, end + shift, true);
+ }
+ }
+
+ public static class UpdatedLineRange {
+ public final int startLine;
+ public final int endLine;
+ public final boolean damaged;
+
+ public UpdatedLineRange(int startLine, int endLine, boolean damaged) {
+ this.startLine = startLine;
+ this.endLine = endLine;
+ this.damaged = damaged;
+ }
+ }
+
//
// Types
//
import java.util.List;
import java.util.Map;
-public class OnesideFragmentBuilderAutoTest extends AutoTestCase {
+public class UnifiedFragmentBuilderAutoTest extends AutoTestCase {
private static ComparisonManager myComparisonManager = new ComparisonManagerImpl();
private static final int CHAR_COUNT = 12;
List<LineFragment> fragments = myComparisonManager.compareLinesInner(sequence1, sequence2,
policy, DumbProgressIndicator.INSTANCE);
- OnesideFragmentBuilder builder = new OnesideFragmentBuilder(fragments, document1, document2, masterSide);
+ UnifiedFragmentBuilder builder = new UnifiedFragmentBuilder(fragments, document1, document2, masterSide);
builder.exec();
boolean ignoreWhitespaces = policy != ComparisonPolicy.DEFAULT;
import java.util.Collections;
import java.util.List;
-public class OnesideFragmentBuilderTest extends UsefulTestCase {
+public class UnifiedFragmentBuilderTest extends UsefulTestCase {
private static ComparisonManager myComparisonManager = new ComparisonManagerImpl();
public void testEquals() {
List<LineFragment> fragments = myComparisonManager.compareLinesInner(document1.getCharsSequence(), document2.getCharsSequence(),
ComparisonPolicy.DEFAULT, DumbProgressIndicator.INSTANCE);
- OnesideFragmentBuilder builder = new OnesideFragmentBuilder(fragments, document1, document2, Side.LEFT);
+ UnifiedFragmentBuilder builder = new UnifiedFragmentBuilder(fragments, document1, document2, Side.LEFT);
builder.exec();
assertTrue(builder.isEqual());
List<LineFragment> fragments = myComparisonManager.compareLinesInner(document1.getCharsSequence(), document2.getCharsSequence(),
ComparisonPolicy.DEFAULT, DumbProgressIndicator.INSTANCE);
- OnesideFragmentBuilder builder = new OnesideFragmentBuilder(fragments, document1, document2, Side.RIGHT);
+ UnifiedFragmentBuilder builder = new UnifiedFragmentBuilder(fragments, document1, document2, Side.RIGHT);
builder.exec();
assertFalse(builder.isEqual());
String title = DiffRequestFactory.getInstance().getTitle(file);
List<String> titles = ContainerUtil.list(beforeRevisionTitle, "Base Version", afterRevisionTitle);
- // Yep, we hope that it's a text file. And that charset wasn't changed.
+ DiffContentFactory contentFactory = DiffContentFactory.getInstance();
List<DiffContent> contents = ContainerUtil.list(
- createTextContent(mergeData.CURRENT, file),
- createTextContent(mergeData.ORIGINAL, file),
- createTextContent(mergeData.LAST, file)
+ contentFactory.createFromBytes(project, file, mergeData.CURRENT),
+ contentFactory.createFromBytes(project, file, mergeData.ORIGINAL),
+ contentFactory.createFromBytes(project, file, mergeData.LAST)
);
return new SimpleDiffRequest(title, contents, titles);
LOG.info(e);
throw new DiffRequestProducerException(e);
}
+ catch (IOException e) {
+ LOG.info(e);
+ throw new DiffRequestProducerException(e);
+ }
}
else {
ContentRevision bRev = change.getBeforeRevision();
import com.intellij.diff.requests.ContentDiffRequest;
import com.intellij.diff.tools.util.DiffSplitter;
import com.intellij.diff.tools.util.SyncScrollSupport;
-import com.intellij.diff.tools.util.twoside.TwosideTextDiffViewer;
+import com.intellij.diff.tools.util.side.TwosideTextDiffViewer;
import com.intellij.diff.util.*;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Document;
myWrapperRequest = request;
myDiffChanges = diffChanges;
- assert getEditor1() != null && getEditor2() != null;
-
for (EditorEx editor : getEditors()) {
if (editor == null) continue;
EditorSettings settings = editor.getSettings();
}
for (DiffChange change : myDiffChanges) {
- DiffDrawUtil.createBorderLineMarker(getEditor1(), change.myEndLine1, SeparatorPlacement.TOP);
- DiffDrawUtil.createBorderLineMarker(getEditor2(), change.myEndLine2, SeparatorPlacement.TOP);
+ DiffDrawUtil.createBorderLineMarker(getEditor(Side.LEFT), change.myEndLine1, SeparatorPlacement.TOP);
+ DiffDrawUtil.createBorderLineMarker(getEditor(Side.RIGHT), change.myEndLine2, SeparatorPlacement.TOP);
}
DiffSplitter splitter = myContentPanel.getSplitter();
- assert splitter != null;
splitter.setDividerWidth(120);
splitter.setShowDividerIcon(false);
}
myContentPanel.setPainter(new MyDividerPainter());
}
- @NotNull
- @Override
- protected boolean[] checkForceReadOnly() {
- return new boolean[]{true, true};
- }
-
@NotNull
@Override
protected Runnable performRediff(@NotNull ProgressIndicator indicator) {
return new Runnable() {
@Override
public void run() {
- assert getEditor1() != null && getEditor2() != null;
for (DiffChange change : myDiffChanges) {
- setupHighlighting(getEditor1(), change, Side.LEFT);
- setupHighlighting(getEditor2(), change, Side.RIGHT);
+ setupHighlighting(change, Side.LEFT);
+ setupHighlighting(change, Side.RIGHT);
}
}
};
}
- private static void setupHighlighting(@NotNull EditorEx editor, @NotNull DiffChange change, @NotNull Side side) {
+ private void setupHighlighting(@NotNull DiffChange change, @NotNull Side side) {
PropertyRecord record = change.getRecord();
List<? extends LineFragment> fragments = change.getFragments();
assert fragments != null;
+ EditorEx editor = getEditor(side);
DocumentEx document = editor.getDocument();
int shift = document.getLineStartOffset(change.getStartLine(side));
@Override
public void paint(@NotNull Graphics g, @NotNull JComponent divider) {
- assert getEditor1() != null && getEditor2() != null;
Graphics2D gg = DiffDividerDrawUtil.getDividerGraphics(g, divider, getEditor1().getComponent());
Rectangle clip = gg.getClipBounds();
if (clip == null) return;
gg.setColor(DiffDrawUtil.getDividerColor());
gg.fill(clip);
- JComponent header1 = getEditor1().getHeaderComponent();
- JComponent header2 = getEditor2().getHeaderComponent();
+ EditorEx editor1 = getEditor1();
+ EditorEx editor2 = getEditor2();
+
+ JComponent header1 = editor1.getHeaderComponent();
+ JComponent header2 = editor2.getHeaderComponent();
int headerOffset1 = header1 == null ? 0 : header1.getHeight();
int headerOffset2 = header2 == null ? 0 : header2.getHeight();
// TODO: painting is ugly if shift1 != shift2 (ex: search field is opened for one of editors)
- int shift1 = getEditor1().getScrollingModel().getVerticalScrollOffset() - headerOffset1;
- int shift2 = getEditor2().getScrollingModel().getVerticalScrollOffset() - headerOffset2;
+ int shift1 = editor1.getScrollingModel().getVerticalScrollOffset() - headerOffset1;
+ int shift2 = editor2.getScrollingModel().getVerticalScrollOffset() - headerOffset2;
double rotate = shift1 == shift2 ? 0 : Math.atan2(shift2 - shift1, clip.width);
- DiffDividerDrawUtil.paintPolygons(gg, divider.getWidth(), false, rotate == 0, getEditor1(), getEditor2(), this);
+ DiffDividerDrawUtil.paintPolygons(gg, divider.getWidth(), false, rotate == 0, editor1, editor2, this);
for (DiffChange change : myDiffChanges) {
- int y1 = getEditor1().logicalPositionToXY(new LogicalPosition(change.getStartLine(Side.LEFT), 0)).y - shift1;
- int y2 = getEditor2().logicalPositionToXY(new LogicalPosition(change.getStartLine(Side.RIGHT), 0)).y - shift2;
- int endY1 = getEditor1().logicalPositionToXY(new LogicalPosition(change.getEndLine(Side.LEFT), 0)).y - shift1;
- int endY2 = getEditor2().logicalPositionToXY(new LogicalPosition(change.getEndLine(Side.RIGHT), 0)).y - shift2;
+ int y1 = editor1.logicalPositionToXY(new LogicalPosition(change.getStartLine(Side.LEFT), 0)).y - shift1;
+ int y2 = editor2.logicalPositionToXY(new LogicalPosition(change.getStartLine(Side.RIGHT), 0)).y - shift2;
+ int endY1 = editor1.logicalPositionToXY(new LogicalPosition(change.getEndLine(Side.LEFT), 0)).y - shift1;
+ int endY2 = editor2.logicalPositionToXY(new LogicalPosition(change.getEndLine(Side.RIGHT), 0)).y - shift2;
AffineTransform oldTransform = gg.getTransform();
gg.translate(0, y1);
myContent1 = DiffContentFactory.getInstance().create(null, document1);
myContent2 = DiffContentFactory.getInstance().create(null, document2);
myEmbedded = embedded;
+
+ putUserData(DiffUserDataKeys.FORCE_READ_ONLY, true);
}
@NotNull