Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2015-05-13 14:57:26 +02:00
37 changed files with 834 additions and 805 deletions
@@ -71,7 +71,7 @@ public class RefManagerImpl extends RefManager {
private final Project myProject;
private AnalysisScope myScope;
private RefProject myRefProject;
private final ConcurrentMap<PsiAnchor, RefElement> myRefTable = ContainerUtil.newConcurrentMap();
private final Map<PsiAnchor, RefElement> myRefTable = new THashMap<PsiAnchor, RefElement>(); // guarded by myRefTable
private final ConcurrentMap<Module, RefModule> myModules = ContainerUtil.newConcurrentMap();
private final ProjectIterator myProjectIterator = new ProjectIterator();
@@ -129,7 +129,9 @@ public class RefManagerImpl extends RefManager {
public void cleanup() {
myScope = null;
myRefProject = null;
myRefTable.clear();
synchronized (myRefTable) {
myRefTable.clear();
}
myModules.clear();
myContext = null;
@@ -335,7 +337,10 @@ public class RefManagerImpl extends RefManager {
@NotNull
public List<RefElement> getSortedElements() {
List<RefElement> answer = new ArrayList<RefElement>(myRefTable.values());
List<RefElement> answer;
synchronized (myRefTable) {
answer = new ArrayList<RefElement>(myRefTable.values());
}
ContainerUtil.quickSort(answer, new Comparator<RefElement>() {
@Override
public int compare(RefElement o1, RefElement o2) {
@@ -362,15 +367,17 @@ public class RefManagerImpl extends RefManager {
extension.removeReference(refElem);
}
if (element != null && myRefTable.remove(createAnchor(element)) != null) return;
synchronized (myRefTable) {
if (element != null && myRefTable.remove(createAnchor(element)) != null) return;
//PsiElement may have been invalidated and new one returned by getElement() is different so we need to do this stuff.
for (Map.Entry<PsiAnchor, RefElement> entry : myRefTable.entrySet()) {
RefElement value = entry.getValue();
if (value == refElem) {
//PsiElement may have been invalidated and new one returned by getElement() is different so we need to do this stuff.
for (Map.Entry<PsiAnchor, RefElement> entry : myRefTable.entrySet()) {
RefElement value = entry.getValue();
PsiAnchor anchor = entry.getKey();
myRefTable.remove(anchor, refElem);
return;
if (value == refElem) {
myRefTable.remove(anchor);
break;
}
}
}
}
@@ -526,25 +533,25 @@ public class RefManagerImpl extends RefManager {
@Nullable Consumer<T> whenCached) {
PsiAnchor psiAnchor = createAnchor(element);
//noinspection unchecked
T result = (T)myRefTable.get(psiAnchor);
T result;
synchronized (myRefTable) {
//noinspection unchecked
result = (T)myRefTable.get(psiAnchor);
if (result != null) return result;
if (result != null) return result;
if (!isValidPointForReference()) {
//LOG.assertTrue(true, "References may become invalid after process is finished");
return null;
if (!isValidPointForReference()) {
//LOG.assertTrue(true, "References may become invalid after process is finished");
return null;
}
result = factory.create();
if (result == null) return null;
myRefTable.put(psiAnchor, result);
}
result = factory.create();
if (result == null) return null;
RefElement prev = myRefTable.putIfAbsent(psiAnchor, result);
if (prev == null) {
if (whenCached != null) whenCached.consume(result);
}
else {
result = (T)prev;
if (whenCached != null) {
whenCached.consume(result);
}
return result;
@@ -15,10 +15,13 @@
*/
package com.intellij.diff.contents;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@Deprecated
/** @deprecated Use {@link FileContent} and {@link VirtualFile#contentsToByteArray()} */
public interface BinaryFileContent extends FileContent {
/**
* @return Binary representation of content.
@@ -101,7 +101,7 @@ public class DiffContentFactoryImpl extends DiffContentFactory {
if (file.isDirectory()) return new DirectoryContentImpl(project, file);
DocumentContent content = createDocument(project, file);
if (content != null) return content;
return new BinaryFileContentImpl(project, file);
return new FileContentImpl(project, file);
}
@Override
@@ -42,6 +42,7 @@ public abstract class OpenInEditorWithMouseAction extends AnAction implements Du
public void register(@NotNull List<? extends Editor> editors) {
myEditors = editors;
for (Editor editor : editors) {
if (editor == null) continue;
registerCustomShortcutSet(getShortcutSet(), (EditorGutterComponentEx)editor.getGutter());
}
}
@@ -118,7 +119,7 @@ public abstract class OpenInEditorWithMouseAction extends AnAction implements Du
@Nullable
private Editor getEditor(@NotNull Component component) {
for (Editor editor : myEditors) {
if (editor.getGutter() == component) {
if (editor != null && editor.getGutter() == component) {
return editor;
}
}
@@ -30,7 +30,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public abstract class SetEditorSettingsAction extends ActionGroup implements DumbAware {
public class SetEditorSettingsAction extends ActionGroup implements DumbAware {
@NotNull private final TextDiffSettingsHolder.TextDiffSettings myTextSettings;
@NotNull private final List<? extends Editor> myEditors;
@@ -125,7 +125,7 @@ public abstract class SetEditorSettingsAction extends ActionGroup implements Dum
@Override
public void applyDefaults(@NotNull List<? extends Editor> editors) {
for (Editor editor : editors) {
if (editor.getUserData(EditorImpl.FORCED_SOFT_WRAPS) != null) myForcedSoftWrap = true;
if (editor != null && editor.getUserData(EditorImpl.FORCED_SOFT_WRAPS) != null) myForcedSoftWrap = true;
}
super.applyDefaults(editors);
}
@@ -157,8 +157,9 @@ public abstract class SetEditorSettingsAction extends ActionGroup implements Dum
@Override
public void setSelected(AnActionEvent e, boolean state) {
setSelected(state);
for (Editor editor : myEditors) {
setSelected(state);
if (editor == null) continue;
apply(editor, state);
}
}
@@ -171,6 +172,7 @@ public abstract class SetEditorSettingsAction extends ActionGroup implements Dum
public void applyDefaults(@NotNull List<? extends Editor> editors) {
for (Editor editor : editors) {
if (editor == null) continue;
apply(editor, isSelected());
}
}
@@ -25,14 +25,14 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
/**
* Allows to compare binary files
* Allows to compare files
*/
public class BinaryFileContentImpl implements DiffContent, BinaryFileContent {
public class FileContentImpl implements FileContent, BinaryFileContent {
@NotNull private final VirtualFile myFile;
@Nullable private final Project myProject;
@NotNull private final FileType myType;
public BinaryFileContentImpl(@Nullable Project project, @NotNull VirtualFile file) {
public FileContentImpl(@Nullable Project project, @NotNull VirtualFile file) {
assert file.isValid() && !file.isDirectory();
myProject = project;
myFile = file;
@@ -1,60 +0,0 @@
/*
* 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.tools.util.EditorsDiffPanelBase;
import com.intellij.diff.util.TextDiffType;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.fileEditor.FileEditor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class BinaryDiffPanel extends EditorsDiffPanelBase {
@NotNull protected final JPanel INSERTED_CONTENT_NOTIFICATION =
createNotification("Content added", TextDiffType.INSERTED.getColor(null));
@NotNull protected final JPanel REMOVED_CONTENT_NOTIFICATION =
createNotification("Content removed", TextDiffType.DELETED.getColor(null));
@NotNull private final BinaryDiffViewer myViewer;
public BinaryDiffPanel(@NotNull BinaryDiffViewer viewer,
@NotNull BinaryContentPanel editorsPanel,
@NotNull DataProvider dataProvider,
@NotNull DiffContext context) {
super(editorsPanel, dataProvider, context);
myViewer = viewer;
}
@Nullable
@Override
protected JComponent getCurrentEditor() {
FileEditor editor = myViewer.getCurrentEditor();
return editor != null ? editor.getComponent() : null;
}
public void addInsertedContentNotification() {
myNotificationsPanel.add(INSERTED_CONTENT_NOTIFICATION);
myNotificationsPanel.revalidate();
}
public void addRemovedContentNotification() {
myNotificationsPanel.add(REMOVED_CONTENT_NOTIFICATION);
myNotificationsPanel.revalidate();
}
}
@@ -17,9 +17,15 @@ package com.intellij.diff.tools.binary;
import com.intellij.diff.DiffContext;
import com.intellij.diff.actions.impl.FocusOppositePaneAction;
import com.intellij.diff.contents.*;
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.SimpleDiffPanel;
import com.intellij.diff.tools.util.StatusPanel;
import com.intellij.diff.tools.util.base.ListenerDiffViewerBase;
import com.intellij.diff.util.DiffUserDataKeys;
import com.intellij.diff.util.DiffUtil;
@@ -27,6 +33,7 @@ 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;
@@ -42,20 +49,17 @@ 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.ui.IdeBorderFactory;
import com.intellij.util.ui.AnimatedIcon;
import com.intellij.util.ui.AsyncProcessIcon;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.io.IOException;
@@ -65,7 +69,7 @@ import java.util.List;
public class BinaryDiffViewer extends ListenerDiffViewerBase {
public static final Logger LOG = Logger.getInstance(BinaryDiffViewer.class);
@NotNull private final BinaryDiffPanel myPanel;
@NotNull private final SimpleDiffPanel myPanel;
@NotNull private final BinaryContentPanel myContentPanel;
@NotNull private final MyStatusPanel myStatusPanel;
@@ -89,6 +93,7 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
myEditorProvider1 = editors.first.second;
myEditor2 = editors.second.first;
myEditorProvider2 = editors.second.second;
assert myEditor1 != null || myEditor2 != null;
if (myEditor1 != null && myEditor2 != null) {
myEditorFocusListener1 = new MyEditorFocusListener(Side.LEFT);
@@ -102,8 +107,7 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
myContentPanel = new BinaryContentPanel(titlePanel, myEditor1, myEditor2);
myPanel = new BinaryDiffPanel(this, myContentPanel, this, context);
if (myEditor1 == null && myEditor2 == null) myPanel.setErrorContent();
myPanel = new SimpleDiffPanel(myContentPanel, this, context);
myStatusPanel = new MyStatusPanel();
@@ -172,9 +176,9 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
@NotNull
private Pair<FileEditor, FileEditorProvider> createEditor(@NotNull final DiffContent content) throws IOException {
if (content instanceof EmptyContent) return Pair.empty();
if (content instanceof BinaryFileContent) {
if (content instanceof FileContent) {
Project project = myProject != null ? myProject : ProjectManager.getInstance().getDefaultProject();
VirtualFile file = ((BinaryFileContent)content).getFile();
VirtualFile file = ((FileContent)content).getFile();
FileEditorProvider[] providers = FileEditorProviderManager.getInstance().getProviders(project, file);
if (providers.length == 0) throw new IOException("Can't find FileEditorProvider");
@@ -254,7 +258,7 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
@Override
public void run() {
clearDiffPresentation();
myPanel.addInsertedContentNotification();
myPanel.addNotification(DiffNotifications.INSERTED_CONTENT);
}
};
}
@@ -264,13 +268,12 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
@Override
public void run() {
clearDiffPresentation();
myPanel.addRemovedContentNotification();
myPanel.addNotification(DiffNotifications.REMOVED_CONTENT);
}
};
}
// TODO: compare text with image by-byte?
if (!(contents.get(0) instanceof BinaryFileContent) || !(contents.get(1) instanceof BinaryFileContent)) {
if (!(contents.get(0) instanceof FileContent) || !(contents.get(1) instanceof FileContent)) {
return new Runnable() {
@Override
public void run() {
@@ -279,18 +282,41 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
};
}
final BinaryFileContent content1 = (BinaryFileContent)contents.get(0);
final BinaryFileContent content2 = (BinaryFileContent)contents.get(1);
byte[] bytes1 = content1.getBytes();
byte[] bytes2 = content2.getBytes();
final VirtualFile file1 = ((FileContent)contents.get(0)).getFile();
final VirtualFile file2 = ((FileContent)contents.get(1)).getFile();
if (!file1.isValid() || !file2.isValid()) {
return new Runnable() {
@Override
public void run() {
myPanel.addNotification(DiffNotifications.ERROR);
clearDiffPresentation();
}
};
}
final boolean equal = Arrays.equals(bytes1, bytes2);
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 new Runnable() {
@Override
public void run() {
clearDiffPresentation();
if (equal) myPanel.addContentsEqualNotification();
if (equal) myPanel.addNotification(DiffNotifications.EQUAL_CONTENTS);
}
};
}
@@ -299,7 +325,7 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
@Override
public void run() {
clearDiffPresentation();
myPanel.addOperationCanceledNotification();
myPanel.addNotification(DiffNotifications.OPERATION_CANCELED);
}
};
}
@@ -309,7 +335,7 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
@Override
public void run() {
clearDiffPresentation();
myPanel.addDiffErrorNotification();
myPanel.addNotification(DiffNotifications.ERROR);
}
};
}
@@ -333,7 +359,7 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
@Nullable
@Override
public JComponent getPreferredFocusedComponent() {
return myPanel.getPreferredFocusedComponent();
return getCurrentEditor().getPreferredFocusedComponent();
}
@NotNull
@@ -351,8 +377,9 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
return myEditor1;
}
@Nullable
@NotNull
FileEditor getCurrentEditor() {
//noinspection ConstantConditions
return getCurrentSide().select(myEditor1, myEditor2);
}
@@ -366,21 +393,10 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
// Misc
//
@Override
protected boolean tryRediffSynchronously() {
return myPanel.isWindowFocused();
}
@Nullable
@Override
protected OpenFileDescriptor getOpenFileDescriptor() {
ContentDiffRequest request = getRequest();
FileEditor editor = getCurrentEditor();
if (editor == null) return null;
DiffContent content = getCurrentSide().selectNotNull(request.getContents());
return content.getOpenFileDescriptor();
return getCurrentSide().selectNotNull(getRequest().getContents()).getOpenFileDescriptor();
}
public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
@@ -401,10 +417,10 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
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 BinaryFileContent) {
if (content instanceof FileContent) {
Project project = context.getProject();
if (project == null) project = ProjectManager.getInstance().getDefaultProject();
VirtualFile file = ((BinaryFileContent)content).getFile();
VirtualFile file = ((FileContent)content).getFile();
return FileEditorProviderManager.getInstance().getProviders(project, file).length != 0;
}
@@ -413,8 +429,7 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
public static boolean wantShowContent(@NotNull DiffContent content, @NotNull DiffContext context) {
if (content instanceof EmptyContent) return false;
if (content instanceof DocumentContent) return false;
if (content instanceof BinaryFileContent) {
if (content instanceof FileContent) {
if (content.getContentType() == null) return false;
if (content.getContentType().isBinary()) return true;
if (content.getContentType() instanceof UIBasedFileType) return true;
@@ -454,27 +469,10 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase {
return super.getData(dataId);
}
private static class MyStatusPanel extends JPanel {
private final AnimatedIcon myBusySpinner;
public MyStatusPanel() {
super(new BorderLayout());
myBusySpinner = new AsyncProcessIcon("StatusPanelSpinner");
myBusySpinner.setVisible(false);
add(myBusySpinner, BorderLayout.WEST);
setBorder(IdeBorderFactory.createEmptyBorder(0, 4, 0, 4));
}
public void setBusy(boolean busy) {
if (busy) {
myBusySpinner.setVisible(true);
myBusySpinner.resume();
}
else {
myBusySpinner.setVisible(false);
myBusySpinner.suspend();
}
private static class MyStatusPanel extends StatusPanel {
@Override
protected int getChangesCount() {
return -1;
}
}
@@ -153,6 +153,7 @@ class DirDiffViewer implements FrameDiffTool.DiffViewer {
if (content instanceof DirectoryContent) return true;
if (content instanceof FileContent &&
content.getContentType() instanceof ArchiveFileType &&
((FileContent)content).getFile().isValid() &&
((FileContent)content).getFile().isInLocalFileSystem()) {
return true;
}
@@ -106,8 +106,7 @@ public class OnesideDiffPanel extends DiffPanelBase {
// Misc
//
@Nullable
public JComponent getPreferredFocusedComponent() {
return myCurrentCard == GOOD_CONTENT ? myEditor.getContentComponent() : null;
public boolean isGoodContent() {
return myCurrentCard == GOOD_CONTENT;
}
}
@@ -26,25 +26,24 @@ 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.DiffDataKeys;
import com.intellij.diff.tools.util.FoldingModelSupport;
import com.intellij.diff.tools.util.PrevNextDifferenceIterable;
import com.intellij.diff.tools.util.StatusPanel;
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.*;
import com.intellij.diff.util.DiffUserDataKeys;
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.DiffUtil.EditorsVisiblePositions;
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.actionSystem.Separator;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.DiffNavigationContext;
import com.intellij.openapi.diff.LineTokenizer;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
@@ -91,7 +90,7 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
@NotNull private final PrevNextDifferenceIterable myPrevNextDifferenceIterable;
@NotNull private final MyStatusPanel myStatusPanel;
@NotNull private final MyScrollToLineHelper myScrollToLineHelper = new MyScrollToLineHelper();
@NotNull private final MyInitialScrollHelper myInitialScrollHelper = new MyInitialScrollHelper();
@NotNull private final MyFoldingModel myFoldingModel;
@NotNull protected Side myMasterSide = Side.RIGHT;
@@ -166,12 +165,12 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
Side side = DiffUtil.getUserData(myRequest, myContext, DiffUserDataKeys.MASTER_SIDE);
if (side != null && side.select(myActualContent1, myActualContent2) != null) myMasterSide = side;
myScrollToLineHelper.processContext();
myInitialScrollHelper.processContext(myRequest);
}
@CalledInAwt
protected void updateContextHints() {
myScrollToLineHelper.updateContext();
myInitialScrollHelper.updateContext(myRequest);
myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
}
@@ -410,7 +409,7 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
clearDiffPresentation();
if (isEqual) myPanel.addContentsEqualNotification();
if (isEqual) myPanel.addNotification(DiffNotifications.EQUAL_CONTENTS);
TIntFunction separatorLines = myFoldingModel.getLineNumberConvertor();
myEditor.getGutterComponentEx().setLineNumberConvertor(mergeConverters(data.getLineConvertor1(), separatorLines),
@@ -456,7 +455,7 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
myFoldingModel.install(changedLines, myRequest, getFoldingModelSettings());
myScrollToLineHelper.onRediff();
myInitialScrollHelper.onRediff();
myStatusPanel.update();
myPanel.setGoodContent();
@@ -754,7 +753,8 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
@Nullable
@Override
public JComponent getPreferredFocusedComponent() {
return myPanel.getPreferredFocusedComponent();
if (!myPanel.isGoodContent()) return null;
return myEditor.getComponent();
}
@NotNull
@@ -785,11 +785,6 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
// Misc
//
@Override
protected boolean tryRediffSynchronously() {
return myPanel.isWindowFocused();
}
@Nullable
@Override
protected OpenFileDescriptor getOpenFileDescriptor() {
@@ -1241,62 +1236,50 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
}
}
private class MyScrollToLineHelper {
protected boolean myShouldScroll = true;
@Nullable private ScrollToPolicy myScrollToChange;
@Nullable private EditorsVisiblePositions myEditorPosition;
@Nullable private LogicalPosition[] myCaretPosition;
@Nullable private DiffNavigationContext myNavigationContext;
public void processContext() {
myScrollToChange = myRequest.getUserData(DiffUserDataKeysEx.SCROLL_TO_CHANGE);
myEditorPosition = myRequest.getUserData(EditorsVisiblePositions.KEY);
myCaretPosition = myRequest.getUserData(DiffUserDataKeysEx.EDITORS_CARET_POSITION);
myNavigationContext = myRequest.getUserData(DiffUserDataKeysEx.NAVIGATION_CONTEXT);
private class MyInitialScrollHelper extends InitialScrollPositionSupport.TwosideInitialScrollHelper {
@NotNull
@Override
protected List<? extends Editor> getEditors() {
return OnesideDiffViewer.this.getEditors();
}
public void updateContext() {
@Override
protected void disableSyncScroll(boolean value) {
}
@Override
public void onSlowRediff() {
// Will not happen for initial rediff
}
@Nullable
@Override
protected LogicalPosition[] getCaretPositions() {
LogicalPosition position = myEditor.getCaretModel().getLogicalPosition();
Pair<int[], Side> pair = transferLineFromOneside(position.line);
LogicalPosition[] carets = new LogicalPosition[2];
carets[0] = getPosition(pair.first[0], position.column);
carets[1] = getPosition(pair.first[1], position.column);
EditorsVisiblePositions editorsPosition = new EditorsVisiblePositions(position, DiffUtil.getScrollingPosition(myEditor));
myRequest.putUserData(DiffUserDataKeysEx.SCROLL_TO_CHANGE, null);
myRequest.putUserData(EditorsVisiblePositions.KEY, editorsPosition);
myRequest.putUserData(DiffUserDataKeysEx.EDITORS_CARET_POSITION, carets);
myRequest.putUserData(DiffUserDataKeysEx.NAVIGATION_CONTEXT, null);
return carets;
}
public void onRediff() {
if (myShouldScroll && myScrollToChange != null) {
myShouldScroll = !doScrollToChange(myScrollToChange);
}
if (myShouldScroll && myNavigationContext != null) {
myShouldScroll = !doScrollToContext(myNavigationContext);
}
if (myShouldScroll && myCaretPosition != null && myCaretPosition.length == 2) {
LogicalPosition twosidePosition = myMasterSide.selectNotNull(myCaretPosition);
int onesideLine = transferLineToOneside(myMasterSide, twosidePosition.line);
LogicalPosition position = new LogicalPosition(onesideLine, twosidePosition.column);
@Override
protected boolean doScrollToPosition() {
if (myCaretPosition == null) return false;
myEditor.getCaretModel().moveToLogicalPosition(position);
LogicalPosition twosidePosition = myMasterSide.selectNotNull(myCaretPosition);
int onesideLine = transferLineToOneside(myMasterSide, twosidePosition.line);
LogicalPosition position = new LogicalPosition(onesideLine, twosidePosition.column);
if (myEditorPosition != null && myEditorPosition.isSame(position)) {
DiffUtil.scrollToPoint(myEditor, myEditorPosition.myPoints[0]);
}
else {
DiffUtil.scrollToCaret(myEditor, false);
}
myShouldScroll = false;
myEditor.getCaretModel().moveToLogicalPosition(position);
if (myEditorsPosition != null && myEditorsPosition.isSame(position)) {
DiffUtil.scrollToPoint(myEditor, myEditorsPosition.myPoints[0], false);
}
if (myShouldScroll) {
doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
else {
DiffUtil.scrollToCaret(myEditor, false);
}
myShouldScroll = false;
return true;
}
@NotNull
@@ -1305,9 +1288,15 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
return new LogicalPosition(line, column);
}
private boolean doScrollToLine(@NotNull Side side, @NotNull LogicalPosition position) {
private void doScrollToLine(@NotNull Side side, @NotNull LogicalPosition position) {
int onesideLine = transferLineToOneside(side, position.line);
DiffUtil.scrollEditor(myEditor, onesideLine, position.column, false);
}
@Override
protected boolean doScrollToLine() {
if (myScrollToLine == null) return false;
doScrollToLine(myScrollToLine.first, new LogicalPosition(myScrollToLine.second, 0));
return true;
}
@@ -1332,23 +1321,37 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
return true;
}
private boolean doScrollToContext(@NotNull DiffNavigationContext context) {
@Override
protected boolean doScrollToChange() {
if (myScrollToChange == null) return false;
return doScrollToChange(myScrollToChange);
}
@Override
protected boolean doScrollToFirstChange() {
return doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
}
@Override
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, context);
NavigationContextChecker checker = new NavigationContextChecker(changedLinesIterator, myNavigationContext);
int line = checker.contextMatchCheck();
if (line == -1) {
// this will work for the case, when spaces changes are ignored, and corresponding fragments are not reported as changed
// just try to find target line -> +-
AllLinesIterator allLinesIterator = new AllLinesIterator(Side.RIGHT);
NavigationContextChecker checker2 = new NavigationContextChecker(allLinesIterator, context);
NavigationContextChecker checker2 = new NavigationContextChecker(allLinesIterator, myNavigationContext);
line = checker2.contextMatchCheck();
}
if (line == -1) return false;
return doScrollToLine(Side.RIGHT, new LogicalPosition(line, 0));
doScrollToLine(Side.RIGHT, new LogicalPosition(line, 0));
return true;
}
}
@@ -30,7 +30,6 @@ import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.CalledWithWriteLock;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -180,6 +179,10 @@ public class SimpleDiffChange {
return DiffUtil.getLineDiffType(myFragment);
}
public boolean isValid() {
return myIsValid;
}
//
// Shift
//
@@ -222,41 +225,6 @@ public class SimpleDiffChange {
return DiffUtil.isSelectedByLine(line, line1, line2);
}
@CalledWithWriteLock
public void replaceChange(@NotNull final Side sourceSide) {
assert myEditor1 != null && myEditor2 != null;
if (!myIsValid) return;
final Document document1 = myEditor1.getDocument();
final Document document2 = myEditor2.getDocument();
DiffUtil.applyModification(sourceSide.other().select(document1, document2),
getStartLine(sourceSide.other()), getEndLine(sourceSide.other()),
sourceSide.select(document1, document2),
getStartLine(sourceSide), getEndLine(sourceSide));
destroyHighlighter();
}
@CalledWithWriteLock
public void appendChange(@NotNull final Side sourceSide) {
assert myEditor1 != null && myEditor2 != null;
if (!myIsValid) return;
if (getStartLine(sourceSide) == getEndLine(sourceSide)) return;
final Document document1 = myEditor1.getDocument();
final Document document2 = myEditor2.getDocument();
DiffUtil.applyModification(sourceSide.other().select(document1, document2),
getEndLine(sourceSide.other()), getEndLine(sourceSide.other()),
sourceSide.select(document1, document2),
getStartLine(sourceSide), getEndLine(sourceSide));
destroyHighlighter();
}
//
// Helpers
//
@@ -330,7 +298,7 @@ public class SimpleDiffChange {
return createIconRenderer(side, "Replace", AllIcons.Diff.Arrow, new Runnable() {
@Override
public void run() {
replaceChange(side);
myViewer.replaceChange(SimpleDiffChange.this, side);
}
});
}
@@ -340,7 +308,7 @@ public class SimpleDiffChange {
return createIconRenderer(side, "Insert", AllIcons.Diff.ArrowLeftDown, new Runnable() {
@Override
public void run() {
appendChange(side);
myViewer.appendChange(SimpleDiffChange.this, side);
}
});
}
@@ -350,7 +318,7 @@ public class SimpleDiffChange {
return createIconRenderer(side.other(), "Revert", AllIcons.Diff.Remove, new Runnable() {
@Override
public void run() {
replaceChange(side.other());
myViewer.replaceChange(SimpleDiffChange.this, side.other());
}
});
}
@@ -77,6 +77,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
@NotNull private final List<SimpleDiffChange> myInvalidDiffChanges = new ArrayList<SimpleDiffChange>();
@Nullable private final MyFoldingModel myFoldingModel;
@NotNull private final MyInitialScrollHelper myInitialScrollHelper = new MyInitialScrollHelper();
@NotNull private final ModifierProvider myModifierProvider;
public SimpleDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
@@ -157,10 +158,17 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
return new MyFoldingModel(editor1, editor2, this);
}
@Override
protected void processContextHints() {
super.processContextHints();
myInitialScrollHelper.processContext(myRequest);
}
@Override
protected void updateContextHints() {
super.updateContextHints();
if (myFoldingModel != null) myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
myInitialScrollHelper.updateContext(myRequest);
super.updateContextHints();
}
//
@@ -171,6 +179,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
protected void onSlowRediff() {
super.onSlowRediff();
myStatusPanel.setBusy(true);
myInitialScrollHelper.onSlowRediff();
}
@Override
@@ -241,7 +250,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
@Override
public void run() {
clearDiffPresentation();
myPanel.addTooBigContentNotification();
myPanel.addNotification(DiffNotifications.DIFF_TOO_BIG);
}
};
}
@@ -250,7 +259,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
@Override
public void run() {
clearDiffPresentation();
myPanel.addOperationCanceledNotification();
myPanel.addNotification(DiffNotifications.OPERATION_CANCELED);
}
};
}
@@ -260,7 +269,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
@Override
public void run() {
clearDiffPresentation();
myPanel.addDiffErrorNotification();
myPanel.addNotification(DiffNotifications.ERROR);
}
};
}
@@ -277,7 +286,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
if (myFoldingModel != null) myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
clearDiffPresentation();
if (data.isEqualContent()) myPanel.addContentsEqualNotification();
if (data.isEqualContent()) myPanel.addNotification(DiffNotifications.EQUAL_CONTENTS);
if (data.getFragments() != null) {
for (LineFragment fragment : data.getFragments()) {
@@ -290,7 +299,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
myFoldingModel.install(data.getFragments(), myRequest, getFoldingModelSettings());
}
scrollOnRediff();
myInitialScrollHelper.onRediff();
myContentPanel.repaintDivider();
myStatusPanel.update();
@@ -386,7 +395,6 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
}
@CalledInAwt
@Override
protected boolean doScrollToChange(@NotNull ScrollToPolicy scrollToPolicy) {
if (myDiffChanges.isEmpty()) return false;
if (myEditor1 == null || myEditor2 == null) return true;
@@ -423,7 +431,6 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
mySyncScrollSupport.makeVisible(getCurrentSide(), line1, endLine1, line2, endLine2, animated);
}
@Override
protected boolean doScrollToContext(@NotNull DiffNavigationContext context) {
if (myEditor2 == null) return false;
@@ -697,7 +704,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
@Override
protected void apply(@NotNull Side side, @NotNull List<SimpleDiffChange> changes) {
for (SimpleDiffChange change : changes) {
change.replaceChange(side);
replaceChange(change, side);
}
}
}
@@ -716,7 +723,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
@Override
protected void apply(@NotNull Side side, @NotNull List<SimpleDiffChange> changes) {
for (SimpleDiffChange change : changes) {
change.appendChange(side);
appendChange(change, side);
}
}
}
@@ -735,11 +742,48 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
@Override
protected void apply(@NotNull Side side, @NotNull List<SimpleDiffChange> changes) {
for (SimpleDiffChange change : changes) {
change.replaceChange(side.other());
replaceChange(change, side.other());
}
}
}
@CalledWithWriteLock
public void replaceChange(@NotNull SimpleDiffChange change, @NotNull final Side sourceSide) {
assert myEditor1 != null && myEditor2 != null;
if (!change.isValid()) return;
final Document document1 = myEditor1.getDocument();
final Document document2 = myEditor2.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));
change.destroyHighlighter();
myDiffChanges.remove(change);
}
@CalledWithWriteLock
public void appendChange(@NotNull SimpleDiffChange change, @NotNull final Side sourceSide) {
assert myEditor1 != null && myEditor2 != null;
if (!change.isValid()) return;
if (change.getStartLine(sourceSide) == change.getEndLine(sourceSide)) return;
final Document document1 = myEditor1.getDocument();
final Document document2 = myEditor2.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));
change.destroyHighlighter();
myDiffChanges.remove(change);
}
private class MyToggleExpandByDefaultAction extends ToggleExpandByDefaultAction {
@Override
protected void expandAll(boolean expand) {
@@ -874,7 +918,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
@Override
public void paint(@NotNull Graphics g, @NotNull JComponent divider) {
if (myEditor1 == null || myEditor2 == null) return;
Graphics2D gg = getDividerGraphics(g, divider);
Graphics2D gg = DiffDividerDrawUtil.getDividerGraphics(g, divider, myEditor1.getComponent());
gg.setColor(DiffDrawUtil.getDividerColor(myEditor1));
gg.fill(gg.getClipBounds());
@@ -1050,4 +1094,26 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
myPaintable.paintOnDivider(gg, divider);
}
}
private class MyInitialScrollHelper extends MyInitialScrollPositionHelper {
@Override
protected boolean doScrollToChange() {
if (myScrollToChange == null) return false;
SimpleDiffViewer.this.doScrollToChange(myScrollToChange);
return true;
}
@Override
protected boolean doScrollToFirstChange() {
SimpleDiffViewer.this.doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
return true;
}
@Override
protected boolean doScrollToContext() {
if (myNavigationContext == null) return false;
SimpleDiffViewer.this.doScrollToContext(myNavigationContext);
return true;
}
}
}
@@ -73,6 +73,7 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
@NotNull private final List<SimpleThreesideDiffChange> myInvalidDiffChanges = new ArrayList<SimpleThreesideDiffChange>();
@NotNull private final MyFoldingModel myFoldingModel;
@NotNull private final MyInitialScrollHelper myInitialScrollHelper = new MyInitialScrollHelper();
public SimpleThreesideDiffViewer(@NotNull DiffContext context, @NotNull DiffRequest request) {
super(context, (ContentDiffRequest)request);
@@ -134,10 +135,17 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
return group;
}
@Override
protected void processContextHints() {
super.processContextHints();
myInitialScrollHelper.processContext(myRequest);
}
@Override
protected void updateContextHints() {
super.updateContextHints();
myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
myInitialScrollHelper.updateContext(myRequest);
}
//
@@ -148,6 +156,7 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
protected void onSlowRediff() {
super.onSlowRediff();
myStatusPanel.setBusy(true);
myInitialScrollHelper.onSlowRediff();
}
@Override
@@ -193,7 +202,7 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
@Override
public void run() {
clearDiffPresentation();
myPanel.addTooBigContentNotification();
myPanel.addNotification(DiffNotifications.DIFF_TOO_BIG);
}
};
}
@@ -202,7 +211,7 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
@Override
public void run() {
clearDiffPresentation();
myPanel.addOperationCanceledNotification();
myPanel.addNotification(DiffNotifications.OPERATION_CANCELED);
}
};
}
@@ -212,7 +221,7 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
@Override
public void run() {
clearDiffPresentation();
myPanel.addDiffErrorNotification();
myPanel.addNotification(DiffNotifications.ERROR);
}
};
}
@@ -238,7 +247,7 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
myFoldingModel.install(fragments, myRequest, getFoldingModelSettings());
scrollOnRediff();
myInitialScrollHelper.onRediff();
myContentPanel.repaintDividers();
myStatusPanel.update();
@@ -324,7 +333,6 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
}
@CalledInAwt
@Override
protected boolean doScrollToChange(@NotNull ScrollToPolicy scrollToPolicy) {
if (myDiffChanges.isEmpty()) return false;
@@ -591,7 +599,7 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
@Override
public void paint(@NotNull Graphics g, @NotNull JComponent divider) {
Graphics2D gg = getDividerGraphics(g, divider);
Graphics2D gg = DiffDividerDrawUtil.getDividerGraphics(g, divider, myEditors.get(0).getComponent());
gg.setColor(DiffDrawUtil.getDividerColor(myEditors.get(0)));
gg.fill(gg.getClipBounds());
@@ -689,4 +697,19 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
myPaintable2.paintOnScrollbar(gg, width);
}
}
private class MyInitialScrollHelper extends MyInitialScrollPositionHelper {
@Override
protected boolean doScrollToChange() {
if (myScrollToChange == null) return false;
SimpleThreesideDiffViewer.this.doScrollToChange(myScrollToChange);
return true;
}
@Override
protected boolean doScrollToFirstChange() {
SimpleThreesideDiffViewer.this.doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
return true;
}
}
}
@@ -0,0 +1,56 @@
/*
* 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.diff.comparison.DiffTooBigException;
import com.intellij.diff.util.TextDiffType;
import com.intellij.openapi.diff.DiffBundle;
import com.intellij.ui.EditorNotificationPanel;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
public class DiffNotifications {
@NotNull public static final JPanel INSERTED_CONTENT =
createNotification("Content added", TextDiffType.INSERTED.getColor(null));
@NotNull public static final JPanel REMOVED_CONTENT =
createNotification("Content removed", TextDiffType.DELETED.getColor(null));
@NotNull public static final JPanel EQUAL_CONTENTS =
createNotification(DiffBundle.message("diff.contents.are.identical.message.text"));
@NotNull public static final JPanel ERROR =
createNotification("Can not calculate diff");
@NotNull public static final JPanel OPERATION_CANCELED =
createNotification("Can not calculate diff. Operation canceled.");
@NotNull public static final JPanel DIFF_TOO_BIG =
createNotification("Can not calculate diff. " + DiffTooBigException.MESSAGE);
@NotNull
public static JPanel createNotification(@NotNull String text) {
return new EditorNotificationPanel().text(text);
}
@NotNull
public static JPanel createNotification(@NotNull String text, @NotNull final Color background) {
return new EditorNotificationPanel() {
@Override
public Color getBackground() {
return background;
}
}.text(text);
}
}
@@ -20,20 +20,19 @@ import com.intellij.diff.tools.util.base.DiffPanelBase;
import com.intellij.diff.util.DiffUtil;
import com.intellij.openapi.actionSystem.DataProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
public abstract class EditorsDiffPanelBase extends DiffPanelBase {
public class SimpleDiffPanel extends DiffPanelBase {
private static final String GOOD_CONTENT = "GoodContent";
private static final String ERROR_CONTENT = "ErrorContent";
@NotNull private final JComponent myEditorsPanel;
public EditorsDiffPanelBase(@NotNull JComponent editorPanel,
@NotNull DataProvider dataProvider,
@NotNull DiffContext context) {
public SimpleDiffPanel(@NotNull JComponent editorPanel,
@NotNull DataProvider dataProvider,
@NotNull DiffContext context) {
super(context.getProject(), dataProvider, context);
myEditorsPanel = editorPanel;
@@ -63,17 +62,7 @@ public abstract class EditorsDiffPanelBase extends DiffPanelBase {
// Misc
//
@Nullable
public JComponent getPreferredFocusedComponent() {
if (myCurrentCard != GOOD_CONTENT) return null;
return getCurrentEditor();
public boolean isGoodContent() {
return myCurrentCard == GOOD_CONTENT;
}
//
// Abstract
//
@Nullable
protected abstract JComponent getCurrentEditor();
}
@@ -30,6 +30,7 @@ public abstract class StatusPanel extends JPanel {
public StatusPanel() {
super(new BorderLayout());
myTextLabel = new JLabel("");
myTextLabel.setVisible(false);
myBusySpinner = new AsyncProcessIcon("StatusPanelSpinner");
myBusySpinner.setVisible(false);
@@ -40,6 +41,7 @@ public abstract class StatusPanel extends JPanel {
public void update() {
int count = getChangesCount();
myTextLabel.setVisible(count != -1);
myTextLabel.setText(DiffBundle.message("diff.count.differences.status.text", count));
}
@@ -17,6 +17,7 @@ package com.intellij.diff.tools.util;
import com.intellij.diff.util.IntPair;
import com.intellij.diff.util.Side;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.ScrollingModel;
@@ -33,6 +34,8 @@ import java.awt.*;
import java.util.List;
public class SyncScrollSupport {
private static final Logger LOG = Logger.getInstance(SyncScrollSupport.class);
public interface SyncScrollable {
@CalledInAwt
boolean isSyncScrollEnabled();
@@ -49,7 +52,8 @@ public class SyncScrollSupport {
@NotNull private final MyScrollHelper myHelper1;
@NotNull private final MyScrollHelper myHelper2;
public boolean myDuringSyncScroll = false;
private boolean myDisabled = false;
private boolean myDuringSyncScroll = false;
public TwosideSyncScrollSupport(@NotNull Editor editor1, @NotNull Editor editor2, @NotNull SyncScrollable scrollable) {
myEditor1 = editor1;
@@ -60,8 +64,22 @@ public class SyncScrollSupport {
myHelper2 = create(myEditor2, myEditor1, myScrollable, Side.RIGHT);
}
public boolean isDuringSyncScroll() {
return myDuringSyncScroll;
}
public boolean setDisabled(boolean value) {
if (myDisabled == value) LOG.warn(new Throwable("myDisabled == value: " + myDisabled + " - " + value));
return myDisabled = value;
}
@NotNull
public SyncScrollable getScrollable() {
return myScrollable;
}
public void visibleAreaChanged(VisibleAreaEvent e) {
if (!myScrollable.isSyncScrollEnabled() || myDuringSyncScroll) return;
if (!myScrollable.isSyncScrollEnabled() || myDuringSyncScroll || myDisabled) return;
myDuringSyncScroll = true;
try {
@@ -77,15 +95,6 @@ public class SyncScrollSupport {
}
}
@NotNull
public SyncScrollable getScrollable() {
return myScrollable;
}
public boolean isDuringSyncScroll() {
return myDuringSyncScroll;
}
public void makeVisible(@NotNull Side masterSide,
int startLine1, int endLine1, int startLine2, int endLine2,
final boolean animate) {
@@ -142,7 +151,8 @@ public class SyncScrollSupport {
@NotNull private final MyScrollHelper myHelper21;
@NotNull private final MyScrollHelper myHelper22;
public boolean myDuringSyncScroll = false;
private boolean myDisabled = false;
private boolean myDuringSyncScroll = false;
public ThreesideSyncScrollSupport(@NotNull List<? extends Editor> editors,
@NotNull SyncScrollable scrollable1,
@@ -160,8 +170,13 @@ public class SyncScrollSupport {
myHelper22 = create(editors.get(2), editors.get(1), myScrollable2, Side.RIGHT);
}
public boolean setDisabled(boolean value) {
if (myDisabled == value) LOG.warn(new Throwable("myDisabled == value: " + myDisabled + " - " + value));
return myDisabled = value;
}
public void visibleAreaChanged(VisibleAreaEvent e) {
if (myDuringSyncScroll) return;
if (myDuringSyncScroll || myDisabled) return;
myDuringSyncScroll = true;
try {
@@ -16,11 +16,8 @@
package com.intellij.diff.tools.util.base;
import com.intellij.diff.DiffContext;
import com.intellij.diff.comparison.DiffTooBigException;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.diff.DiffBundle;
import com.intellij.openapi.project.Project;
import com.intellij.ui.EditorNotificationPanel;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,15 +26,6 @@ import javax.swing.*;
import java.awt.*;
public abstract class DiffPanelBase extends JPanel implements DataProvider {
@NotNull protected final JPanel CONTENTS_EQUAL_NOTIFICATION =
createNotification(DiffBundle.message("diff.contents.are.identical.message.text"));
@NotNull protected final JPanel CANT_CALCULATE_DIFF =
createNotification("Can not calculate diff");
@NotNull protected final JPanel CONTENTS_OPERATION_CANCELED_NOTIFICATION =
createNotification("Can not calculate diff. Operation canceled.");
@NotNull protected final JPanel CONTENTS_TOO_BIG_NOTIFICATION =
createNotification("Can not calculate diff. " + DiffTooBigException.MESSAGE);
@Nullable protected final Project myProject;
@NotNull private final DataProvider myDataProvider;
@NotNull protected final DiffContext myContext;
@@ -82,10 +70,6 @@ public abstract class DiffPanelBase extends JPanel implements DataProvider {
return null;
}
public boolean isWindowFocused() {
return myContext.isWindowFocused();
}
public boolean isFocused() {
return myContext.isFocused();
}
@@ -114,50 +98,17 @@ public abstract class DiffPanelBase extends JPanel implements DataProvider {
return myDataProvider.getData(dataId);
}
@Nullable
public abstract JComponent getPreferredFocusedComponent();
//
// Notifications
//
public void addContentsEqualNotification() {
myNotificationsPanel.add(CONTENTS_EQUAL_NOTIFICATION);
myNotificationsPanel.revalidate();
}
public void addTooBigContentNotification() {
myNotificationsPanel.add(CONTENTS_TOO_BIG_NOTIFICATION);
myNotificationsPanel.revalidate();
}
public void addOperationCanceledNotification() {
myNotificationsPanel.add(CONTENTS_OPERATION_CANCELED_NOTIFICATION);
myNotificationsPanel.revalidate();
}
public void addDiffErrorNotification() {
myNotificationsPanel.add(CANT_CALCULATE_DIFF);
myNotificationsPanel.revalidate();
}
public void resetNotifications() {
myNotificationsPanel.removeAll();
myNotificationsPanel.revalidate();
}
@NotNull
public static JPanel createNotification(@NotNull String text) {
return new EditorNotificationPanel().text(text);
}
@NotNull
public static JPanel createNotification(@NotNull String text, @NotNull final Color background) {
return new EditorNotificationPanel() {
@Override
public Color getBackground() {
return background;
}
}.text(text);
public void addNotification(@NotNull JComponent notification) {
myNotificationsPanel.add(notification);
myNotificationsPanel.revalidate();
}
}
@@ -147,13 +147,17 @@ public abstract class DiffViewerBase implements DiffViewer, DataProvider {
return myRequest;
}
public boolean isDisposed() {
return myDisposed.get();
}
//
// Abstract
//
@CalledInAwt
protected boolean tryRediffSynchronously() {
return true;
return myContext.isWindowFocused();
}
@Nullable
@@ -0,0 +1,282 @@
/*
* 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.base;
import com.intellij.diff.requests.DiffRequest;
import com.intellij.diff.util.*;
import com.intellij.diff.util.DiffUserDataKeysEx.ScrollToPolicy;
import com.intellij.openapi.diff.DiffNavigationContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.CalledInAwt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.List;
public class InitialScrollPositionSupport {
public abstract static class InitialScrollHelperBase {
protected boolean myShouldScroll = true;
@Nullable protected ScrollToPolicy myScrollToChange;
@Nullable protected EditorsVisiblePositions myEditorsPosition;
@Nullable protected LogicalPosition[] myCaretPosition;
public void processContext(@NotNull DiffRequest request) {
myScrollToChange = request.getUserData(DiffUserDataKeysEx.SCROLL_TO_CHANGE);
myEditorsPosition = request.getUserData(EditorsVisiblePositions.KEY);
myCaretPosition = request.getUserData(DiffUserDataKeysEx.EDITORS_CARET_POSITION);
}
public void updateContext(@NotNull DiffRequest request) {
LogicalPosition[] carets = getCaretPositions();
EditorsVisiblePositions visiblePositions = getVisiblePositions();
request.putUserData(DiffUserDataKeysEx.SCROLL_TO_CHANGE, null);
request.putUserData(EditorsVisiblePositions.KEY, visiblePositions);
request.putUserData(DiffUserDataKeysEx.EDITORS_CARET_POSITION, carets);
}
@Nullable
protected abstract LogicalPosition[] getCaretPositions();
@Nullable
protected abstract EditorsVisiblePositions getVisiblePositions();
}
private static abstract class SideInitialScrollHelper extends InitialScrollHelperBase {
@Nullable
@Override
protected LogicalPosition[] getCaretPositions() {
return doGetCaretPositions(getEditors());
}
@Nullable
@Override
protected EditorsVisiblePositions getVisiblePositions() {
return doGetVisiblePositions(getEditors());
}
@CalledInAwt
protected boolean doScrollToPosition() {
List<? extends Editor> editors = getEditors();
if (myCaretPosition == null || myCaretPosition.length != editors.size()) return false;
doMoveCaretsToPositions(myCaretPosition, editors);
try {
disableSyncScroll(true);
if (myEditorsPosition != null && myEditorsPosition.isSame(myCaretPosition)) {
doScrollToVisiblePositions(myEditorsPosition, editors);
}
else {
doScrollToCaret(editors);
}
}
finally {
disableSyncScroll(false);
}
return true;
}
@NotNull
protected abstract List<? extends Editor> getEditors();
protected abstract void disableSyncScroll(boolean value);
}
public static abstract class TwosideInitialScrollHelper extends SideInitialScrollHelper {
@Nullable protected Pair<Side, Integer> myScrollToLine;
@Nullable protected DiffNavigationContext myNavigationContext;
@Override
public void processContext(@NotNull DiffRequest request) {
super.processContext(request);
myScrollToLine = request.getUserData(DiffUserDataKeys.SCROLL_TO_LINE);
myNavigationContext = request.getUserData(DiffUserDataKeysEx.NAVIGATION_CONTEXT);
}
@Override
public void updateContext(@NotNull DiffRequest request) {
super.updateContext(request);
request.putUserData(DiffUserDataKeys.SCROLL_TO_LINE, null);
request.putUserData(DiffUserDataKeysEx.NAVIGATION_CONTEXT, null);
}
@CalledInAwt
public void onSlowRediff() {
if (wasScrolled(getEditors())) myShouldScroll = false;
if (myScrollToChange != null) return;
if (myShouldScroll) myShouldScroll = !doScrollToLine();
if (myNavigationContext != null) return;
if (myShouldScroll) myShouldScroll = !doScrollToPosition();
}
@CalledInAwt
public void onRediff() {
if (wasScrolled(getEditors())) myShouldScroll = false;
if (myShouldScroll) myShouldScroll = !doScrollToChange();
if (myShouldScroll) myShouldScroll = !doScrollToLine();
if (myShouldScroll) myShouldScroll = !doScrollToContext();
if (myShouldScroll) myShouldScroll = !doScrollToPosition();
if (myShouldScroll) doScrollToFirstChange();
myShouldScroll = false;
}
@CalledInAwt
protected abstract boolean doScrollToChange();
@CalledInAwt
protected abstract boolean doScrollToFirstChange();
@CalledInAwt
protected abstract boolean doScrollToContext();
@CalledInAwt
protected abstract boolean doScrollToLine();
}
public static abstract class ThreesideInitialScrollHelper extends SideInitialScrollHelper {
@Nullable protected Pair<ThreeSide, Integer> myScrollToLine;
@Override
public void processContext(@NotNull DiffRequest request) {
super.processContext(request);
myScrollToLine = request.getUserData(DiffUserDataKeys.SCROLL_TO_LINE_THREESIDE);
}
@Override
public void updateContext(@NotNull DiffRequest request) {
super.updateContext(request);
request.putUserData(DiffUserDataKeys.SCROLL_TO_LINE_THREESIDE, null);
}
public void onSlowRediff() {
if (wasScrolled(getEditors())) myShouldScroll = false;
if (myScrollToChange != null) return;
if (myShouldScroll) myShouldScroll = !doScrollToLine();
if (myShouldScroll) myShouldScroll = !doScrollToPosition();
}
public void onRediff() {
if (wasScrolled(getEditors())) myShouldScroll = false;
if (myShouldScroll) myShouldScroll = !doScrollToChange();
if (myShouldScroll) myShouldScroll = !doScrollToLine();
if (myShouldScroll) myShouldScroll = !doScrollToPosition();
if (myShouldScroll) doScrollToFirstChange();
myShouldScroll = false;
}
@CalledInAwt
protected abstract boolean doScrollToChange();
@CalledInAwt
protected abstract boolean doScrollToFirstChange();
@CalledInAwt
protected abstract boolean doScrollToLine();
@NotNull
protected abstract List<? extends Editor> getEditors();
}
@NotNull
public static Point[] doGetScrollingPositions(@NotNull List<? extends Editor> editors) {
Point[] carets = new Point[editors.size()];
for (int i = 0; i < editors.size(); i++) {
carets[i] = DiffUtil.getScrollingPosition(editors.get(i));
}
return carets;
}
@NotNull
public static LogicalPosition[] doGetCaretPositions(@NotNull List<? extends Editor> editors) {
LogicalPosition[] carets = new LogicalPosition[editors.size()];
for (int i = 0; i < editors.size(); i++) {
carets[i] = DiffUtil.getCaretPosition(editors.get(i));
}
return carets;
}
@Nullable
public static EditorsVisiblePositions doGetVisiblePositions(@NotNull List<? extends Editor> editors) {
LogicalPosition[] carets = doGetCaretPositions(editors);
Point[] points = doGetScrollingPositions(editors);
return new EditorsVisiblePositions(carets, points);
}
public static void doMoveCaretsToPositions(@NotNull LogicalPosition[] positions, @NotNull List<? extends Editor> editors) {
for (int i = 0; i < editors.size(); i++) {
Editor editor = editors.get(i);
if (editor != null) editor.getCaretModel().moveToLogicalPosition(positions[i]);
}
}
public static void doScrollToVisiblePositions(@NotNull EditorsVisiblePositions visiblePositions,
@NotNull List<? extends Editor> editors) {
for (int i = 0; i < editors.size(); i++) {
Editor editor = editors.get(i);
if (editor != null) DiffUtil.scrollToPoint(editor, visiblePositions.myPoints[i], false);
}
}
public static void doScrollToCaret(@NotNull List<? extends Editor> editors) {
for (int i = 0; i < editors.size(); i++) {
Editor editor = editors.get(i);
if (editor != null) DiffUtil.scrollToCaret(editor, false);
}
}
public static boolean wasScrolled(@NotNull List<? extends Editor> editors) {
for (Editor editor : editors) {
if (editor == null) continue;
if (editor.getCaretModel().getOffset() != 0) return true;
if (editor.getScrollingModel().getVerticalScrollOffset() != 0) return true;
if (editor.getScrollingModel().getHorizontalScrollOffset() != 0) return true;
}
return false;
}
public static class EditorsVisiblePositions {
public static final Key<EditorsVisiblePositions> KEY = Key.create("Diff.EditorsVisiblePositions");
@NotNull public final LogicalPosition[] myCaretPosition;
@NotNull public final Point[] myPoints;
public EditorsVisiblePositions(@NotNull LogicalPosition caretPosition, @NotNull Point points) {
this(new LogicalPosition[]{caretPosition}, new Point[]{points});
}
public EditorsVisiblePositions(@NotNull LogicalPosition[] caretPosition, @NotNull Point[] points) {
myCaretPosition = caretPosition;
myPoints = points;
}
public boolean isSame(@Nullable LogicalPosition... caretPosition) {
// TODO: allow small fluctuations ?
if (caretPosition == null) return true;
if (myCaretPosition.length != caretPosition.length) return false;
for (int i = 0; i < caretPosition.length; i++) {
if (!caretPosition[i].equals(myCaretPosition[i])) return false;
}
return true;
}
}
}
@@ -16,9 +16,9 @@
package com.intellij.diff.tools.util.base;
import com.intellij.diff.DiffContext;
import com.intellij.diff.contents.BinaryFileContent;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.contents.DocumentContent;
import com.intellij.diff.contents.FileContent;
import com.intellij.diff.requests.ContentDiffRequest;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.event.DocumentAdapter;
@@ -79,8 +79,8 @@ public abstract class ListenerDiffViewerBase extends DiffViewerBase {
protected VirtualFileListener createFileListener(@NotNull ContentDiffRequest request) {
final List<VirtualFile> files = new ArrayList<VirtualFile>(0);
for (DiffContent content : request.getContents()) {
if (content instanceof BinaryFileContent) {
files.add(((BinaryFileContent)content).getFile());
if (content instanceof FileContent && !(content instanceof DocumentContent)) {
files.add(((FileContent)content).getFile());
}
}
@@ -1,41 +0,0 @@
/*
* 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.tools.util.EditorsDiffPanelBase;
import com.intellij.openapi.actionSystem.DataProvider;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class ThreesideTextDiffPanel extends EditorsDiffPanelBase {
@NotNull private final ThreesideTextDiffViewer myViewer;
public ThreesideTextDiffPanel(@NotNull ThreesideTextDiffViewer viewer,
@NotNull ThreesideTextContentPanel editorPanel,
@NotNull DataProvider dataProvider,
@NotNull DiffContext context) {
super(editorPanel, dataProvider, context);
myViewer = viewer;
}
@NotNull
@Override
protected JComponent getCurrentEditor() {
return myViewer.getCurrentEditor().getContentComponent();
}
}
@@ -24,12 +24,15 @@ 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.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.*;
import com.intellij.diff.util.DiffUserDataKeysEx.ScrollToPolicy;
import com.intellij.diff.util.DiffUtil.EditorsVisiblePositions;
import com.intellij.diff.util.DiffUserDataKeys;
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;
@@ -37,7 +40,6 @@ 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.LogicalPosition;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.VisibleAreaEvent;
import com.intellij.openapi.editor.event.VisibleAreaListener;
@@ -45,7 +47,6 @@ 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.Pair;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.CalledInAwt;
@@ -54,7 +55,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.util.ArrayList;
@@ -65,7 +65,7 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
@NotNull private final EditorFactory myEditorFactory = EditorFactory.getInstance();
@NotNull protected final ThreesideTextDiffPanel myPanel;
@NotNull protected final SimpleDiffPanel myPanel;
@NotNull protected final ThreesideTextContentPanel myContentPanel;
@NotNull protected final List<EditorEx> myEditors;
@@ -81,8 +81,6 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
@NotNull protected final MySetEditorSettingsAction myEditorSettingsAction;
@NotNull private final MyScrollToLineHelper myScrollToLineHelper = new MyScrollToLineHelper();
@Nullable private ThreesideSyncScrollSupport mySyncScrollListener;
@NotNull private ThreeSide myCurrentSide;
@@ -103,7 +101,7 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
myContentPanel = new ThreesideTextContentPanel(myEditors, titlePanel);
myPanel = new ThreesideTextDiffPanel(this, myContentPanel, this, context);
myPanel = new SimpleDiffPanel(myContentPanel, this, context);
//new MyFocusOppositePaneAction().setupAction(myPanel, this); // TODO
@@ -133,14 +131,10 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
protected void processContextHints() {
ThreeSide side = myContext.getUserData(DiffUserDataKeys.PREFERRED_FOCUS_THREESIDE);
if (side != null) myCurrentSide = side;
myScrollToLineHelper.processContext();
}
protected void updateContextHints() {
myContext.putUserData(DiffUserDataKeys.PREFERRED_FOCUS_THREESIDE, myCurrentSide);
myScrollToLineHelper.updateContext();
}
@NotNull
@@ -211,14 +205,12 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
myEditors.get(1).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener2);
myEditors.get(2).getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener2);
if (mySyncScrollListener != null) {
mySyncScrollListener = null;
}
mySyncScrollListener = null;
}
protected void disableSyncScrollSupport(boolean disable) {
if (mySyncScrollListener != null) {
mySyncScrollListener.myDuringSyncScroll = disable;
mySyncScrollListener.setDisabled(disable);
}
}
@@ -233,17 +225,6 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
myContentPanel.repaintDividers();
}
@CalledInAwt
protected void scrollOnRediff() {
myScrollToLineHelper.onRediff();
}
@Override
protected void onSlowRediff() {
super.onSlowRediff();
myScrollToLineHelper.onSlowRediff();
}
//
// Getters
//
@@ -257,7 +238,7 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
@Nullable
@Override
public JComponent getPreferredFocusedComponent() {
return myPanel.getPreferredFocusedComponent();
return getCurrentEditor().getContentComponent();
}
@NotNull
@@ -292,11 +273,6 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
myCurrentSide = side;
}
@CalledInAwt
protected boolean doScrollToChange(@NotNull ScrollToPolicy scrollToChangePolicy) {
return false;
}
@Nullable
protected abstract SyncScrollSupport.SyncScrollable getSyncScrollable(@NotNull Side side);
@@ -304,11 +280,6 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
// Misc
//
@Override
protected boolean tryRediffSynchronously() {
return myPanel.isWindowFocused();
}
@Nullable
@Override
protected OpenFileDescriptor getOpenFileDescriptor() {
@@ -407,15 +378,6 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
return super.getData(dataId);
}
@NotNull
protected Graphics2D getDividerGraphics(@NotNull Graphics g, @NotNull Component divider) {
int width = divider.getWidth();
int editorHeight = myEditors.get(0).getComponent().getHeight();
int dividerOffset = divider.getLocationOnScreen().y;
int editorOffset = myEditors.get(0).getComponent().getLocationOnScreen().y;
return (Graphics2D)g.create(0, editorOffset - dividerOffset, width, editorHeight);
}
private class MyEditorFocusListener extends FocusAdapter {
@NotNull private final ThreeSide mySide;
@@ -447,93 +409,26 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase {
}
}
private class MyScrollToLineHelper {
protected boolean myShouldScroll = true;
@Nullable private ScrollToPolicy myScrollToChange;
@Nullable private EditorsVisiblePositions myEditorsPosition;
@Nullable private LogicalPosition[] myCaretPosition;
@Nullable private Pair<ThreeSide, Integer> myScrollToLine;
public void processContext() {
myScrollToChange = myRequest.getUserData(DiffUserDataKeysEx.SCROLL_TO_CHANGE);
myEditorsPosition = myRequest.getUserData(EditorsVisiblePositions.KEY);
myCaretPosition = myRequest.getUserData(DiffUserDataKeysEx.EDITORS_CARET_POSITION);
myScrollToLine = myRequest.getUserData(DiffUserDataKeys.SCROLL_TO_LINE_THREESIDE);
protected abstract class MyInitialScrollPositionHelper extends InitialScrollPositionSupport.ThreesideInitialScrollHelper {
@NotNull
@Override
protected List<? extends Editor> getEditors() {
return ThreesideTextDiffViewer.this.getEditors();
}
public void updateContext() {
LogicalPosition[] carets = DiffUtil.getCaretPositions(myEditors);
Point[] points = DiffUtil.getScrollingPositions(myEditors);
EditorsVisiblePositions editorsPosition = new EditorsVisiblePositions(carets, points);
myRequest.putUserData(DiffUserDataKeysEx.SCROLL_TO_CHANGE, null);
myRequest.putUserData(EditorsVisiblePositions.KEY, editorsPosition);
myRequest.putUserData(DiffUserDataKeysEx.EDITORS_CARET_POSITION, carets);
myRequest.putUserData(DiffUserDataKeys.SCROLL_TO_LINE_THREESIDE, null);
@Override
protected void disableSyncScroll(boolean value) {
disableSyncScrollSupport(value);
}
public void onSlowRediff() {
if (myScrollToChange != null) return;
if (myShouldScroll && myScrollToLine != null) {
myShouldScroll = !doScrollToLine();
}
if (myShouldScroll && myCaretPosition != null) {
myShouldScroll = !doScrollToPosition();
}
}
public void onRediff() {
if (DiffUtil.wasScrolled(getEditors())) myShouldScroll = false;
if (myShouldScroll && myScrollToChange != null) {
myShouldScroll = !doScrollToChange(myScrollToChange);
}
if (myShouldScroll && myScrollToLine != null) {
myShouldScroll = !doScrollToLine();
}
if (myShouldScroll && myCaretPosition != null) {
myShouldScroll = !doScrollToPosition();
}
if (myShouldScroll) {
doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
}
myShouldScroll = false;
}
private boolean doScrollToPosition() {
if (myCaretPosition == null || myCaretPosition.length != 3) return false;
myEditors.get(0).getCaretModel().moveToLogicalPosition(myCaretPosition[0]);
myEditors.get(1).getCaretModel().moveToLogicalPosition(myCaretPosition[1]);
myEditors.get(2).getCaretModel().moveToLogicalPosition(myCaretPosition[2]);
if (myEditorsPosition != null && myEditorsPosition.isSame(myCaretPosition)) {
try {
disableSyncScrollSupport(true);
DiffUtil.scrollToPoint(myEditors.get(0), myEditorsPosition.myPoints[0]);
DiffUtil.scrollToPoint(myEditors.get(1), myEditorsPosition.myPoints[1]);
DiffUtil.scrollToPoint(myEditors.get(2), myEditorsPosition.myPoints[2]);
}
finally {
disableSyncScrollSupport(false);
}
}
else {
DiffUtil.scrollToCaret(getCurrentEditor(), false);
}
return true;
}
private boolean doScrollToLine() {
@Override
protected boolean doScrollToLine() {
if (myScrollToLine == null) return false;
ThreeSide side = myScrollToLine.first;
Integer line = myScrollToLine.second;
if (side.select(myEditors) == null) return false;
if (side.select(getEditors()) == null) return false;
myCurrentSide = side;
DiffUtil.scrollEditor(getCurrentEditor(), line, false);
scrollToLine(side, line);
return true;
}
}
@@ -1,41 +0,0 @@
/*
* 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.tools.util.EditorsDiffPanelBase;
import com.intellij.openapi.actionSystem.DataProvider;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class TwosideTextDiffPanel extends EditorsDiffPanelBase {
@NotNull private final TwosideTextDiffViewer myViewer;
public TwosideTextDiffPanel(@NotNull TwosideTextDiffViewer viewer,
@NotNull TwosideTextContentPanel content,
@NotNull DataProvider dataProvider,
@NotNull DiffContext context) {
super(content, dataProvider, context);
myViewer = viewer;
}
@NotNull
@Override
protected JComponent getCurrentEditor() {
return myViewer.getCurrentEditor().getContentComponent();
}
}
@@ -21,23 +21,20 @@ 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.contents.FileContent;
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.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.DiffUserDataKeys;
import com.intellij.diff.util.DiffUserDataKeysEx;
import com.intellij.diff.util.DiffUserDataKeysEx.ScrollToPolicy;
import com.intellij.diff.util.DiffUtil;
import com.intellij.diff.util.DiffUtil.EditorsVisiblePositions;
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.diff.DiffNavigationContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.LogicalPosition;
@@ -47,7 +44,6 @@ import com.intellij.openapi.editor.event.VisibleAreaEvent;
import com.intellij.openapi.editor.event.VisibleAreaListener;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.CalledInAwt;
@@ -56,7 +52,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.util.Collections;
@@ -67,7 +62,7 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
@NotNull private final EditorFactory myEditorFactory = EditorFactory.getInstance();
@NotNull protected final TwosideTextDiffPanel myPanel;
@NotNull protected final SimpleDiffPanel myPanel;
@NotNull protected final TwosideTextContentPanel myContentPanel;
@Nullable protected final EditorEx myEditor1;
@@ -82,8 +77,6 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
@NotNull private final MyEditorFocusListener myEditorFocusListener2 = new MyEditorFocusListener(Side.RIGHT);
@NotNull private final MyVisibleAreaListener myVisibleAreaListener = new MyVisibleAreaListener();
@NotNull private final MyScrollToLineHelper myScrollToLineHelper = new MyScrollToLineHelper();
@Nullable protected TwosideSyncScrollSupport mySyncScrollSupport;
@NotNull private Side myCurrentSide;
@@ -108,7 +101,7 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
myContentPanel = new TwosideTextContentPanel(titlePanel, myEditor1, myEditor2);
myPanel = new TwosideTextDiffPanel(this, myContentPanel, this, context);
myPanel = new SimpleDiffPanel(myContentPanel, this, context);
new MyFocusOppositePaneAction(true).setupAction(myPanel);
@@ -149,16 +142,12 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
Side side = myContext.getUserData(DiffUserDataKeys.PREFERRED_FOCUS_SIDE);
if (side != null) myCurrentSide = side;
}
myScrollToLineHelper.processContext();
}
protected void updateContextHints() {
if (myEditor1 != null && myEditor2 != null) {
myContext.putUserData(DiffUserDataKeys.PREFERRED_FOCUS_SIDE, myCurrentSide);
}
myScrollToLineHelper.updateContext();
}
@NotNull
@@ -197,17 +186,6 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
myContentPanel.repaintDivider();
}
@CalledInAwt
protected void scrollOnRediff() {
myScrollToLineHelper.onRediff();
}
@Override
protected void onSlowRediff() {
super.onSlowRediff();
myScrollToLineHelper.onSlowRediff();
}
//
// Listeners
//
@@ -249,16 +227,12 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
myEditor2.getContentComponent().removeFocusListener(myEditorFocusListener2);
myEditor2.getScrollingModel().removeVisibleAreaListener(myVisibleAreaListener);
}
if (myEditor1 != null && myEditor2 != null) {
if (mySyncScrollSupport != null) {
mySyncScrollSupport = null;
}
}
mySyncScrollSupport = null;
}
protected void disableSyncScrollSupport(boolean disable) {
if (mySyncScrollSupport != null) {
mySyncScrollSupport.myDuringSyncScroll = disable;
mySyncScrollSupport.setDisabled(disable);
}
}
@@ -290,7 +264,7 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
@Nullable
@Override
public JComponent getPreferredFocusedComponent() {
return myPanel.getPreferredFocusedComponent();
return getCurrentEditor().getContentComponent();
}
@NotNull
@@ -340,16 +314,6 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
myCurrentSide = side;
}
@CalledInAwt
protected boolean doScrollToChange(@NotNull ScrollToPolicy scrollToChangePolicy) {
return false;
}
@CalledInAwt
protected boolean doScrollToContext(@NotNull DiffNavigationContext context) {
return false;
}
@Nullable
protected abstract SyncScrollSupport.SyncScrollable getSyncScrollable();
@@ -357,11 +321,6 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
// Misc
//
@Override
protected boolean tryRediffSynchronously() {
return myPanel.isWindowFocused();
}
@Nullable
@Override
protected OpenFileDescriptor getOpenFileDescriptor() {
@@ -458,17 +417,6 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
return super.getData(dataId);
}
@NotNull
protected Graphics2D getDividerGraphics(@NotNull Graphics g, @NotNull Component divider) {
assert myEditor1 != null && myEditor2 != null;
int width = divider.getWidth();
int editorHeight = myEditor1.getComponent().getHeight();
int dividerOffset = divider.getLocationOnScreen().y;
int editorOffset = myEditor1.getComponent().getLocationOnScreen().y;
return (Graphics2D)g.create(0, editorOffset - dividerOffset, width, editorHeight);
}
private class MyEditorFocusListener extends FocusAdapter {
@NotNull private final Side mySide;
@@ -495,99 +443,26 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
}
}
private class MyScrollToLineHelper {
protected boolean myShouldScroll = true;
@Nullable private ScrollToPolicy myScrollToChange;
@Nullable private EditorsVisiblePositions myEditorsPosition;
@Nullable private LogicalPosition[] myCaretPosition;
@Nullable private Pair<Side, Integer> myScrollToLine;
@Nullable private DiffNavigationContext myNavigationContext;
public void processContext() {
myScrollToChange = myRequest.getUserData(DiffUserDataKeysEx.SCROLL_TO_CHANGE);
myEditorsPosition = myRequest.getUserData(EditorsVisiblePositions.KEY);
myCaretPosition = myRequest.getUserData(DiffUserDataKeysEx.EDITORS_CARET_POSITION);
myScrollToLine = myRequest.getUserData(DiffUserDataKeys.SCROLL_TO_LINE);
myNavigationContext = myRequest.getUserData(DiffUserDataKeysEx.NAVIGATION_CONTEXT);
protected abstract class MyInitialScrollPositionHelper extends InitialScrollPositionSupport.TwosideInitialScrollHelper {
@NotNull
@Override
protected List<? extends Editor> getEditors() {
return TwosideTextDiffViewer.this.getEditors();
}
public void updateContext() {
List<EditorEx> allEditors = ContainerUtil.list(myEditor1, myEditor2); // we want all editors, not only NotNull ones
LogicalPosition[] carets = DiffUtil.getCaretPositions(allEditors);
Point[] points = DiffUtil.getScrollingPositions(allEditors);
EditorsVisiblePositions editorsPosition = new EditorsVisiblePositions(carets, points);
myRequest.putUserData(DiffUserDataKeysEx.SCROLL_TO_CHANGE, null);
myRequest.putUserData(EditorsVisiblePositions.KEY, editorsPosition);
myRequest.putUserData(DiffUserDataKeysEx.EDITORS_CARET_POSITION, carets);
myRequest.putUserData(DiffUserDataKeys.SCROLL_TO_LINE, null);
myRequest.putUserData(DiffUserDataKeysEx.NAVIGATION_CONTEXT, null);
@Override
protected void disableSyncScroll(boolean value) {
disableSyncScrollSupport(value);
}
public void onSlowRediff() {
if (myScrollToChange != null) return;
if (myNavigationContext != null) return;
if (myShouldScroll && myScrollToLine != null) {
myShouldScroll = !doScrollToLine();
}
if (myShouldScroll && myCaretPosition != null) {
myShouldScroll = !doScrollToPosition(); // TODO: discard Point in this case, scroll to caret ?
}
}
public void onRediff() {
if (DiffUtil.wasScrolled(getEditors())) myShouldScroll = false;
if (myShouldScroll && myScrollToChange != null) {
myShouldScroll = !doScrollToChange(myScrollToChange);
}
if (myShouldScroll && myScrollToLine != null) {
myShouldScroll = !doScrollToLine();
}
if (myShouldScroll && myNavigationContext != null) {
myShouldScroll = !doScrollToContext(myNavigationContext);
}
if (myShouldScroll && myCaretPosition != null) {
myShouldScroll = !doScrollToPosition();
}
if (myShouldScroll) {
doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
}
myShouldScroll = false;
}
private boolean doScrollToPosition() {
if (myCaretPosition == null || myCaretPosition.length != 2) return false;
if (myEditor1 != null) myEditor1.getCaretModel().moveToLogicalPosition(myCaretPosition[0]);
if (myEditor2 != null) myEditor2.getCaretModel().moveToLogicalPosition(myCaretPosition[1]);
if (myEditorsPosition != null && myEditorsPosition.isSame(myCaretPosition)) {
try {
disableSyncScrollSupport(true);
DiffUtil.scrollToPoint(myEditor1, myEditorsPosition.myPoints[0]);
DiffUtil.scrollToPoint(myEditor2, myEditorsPosition.myPoints[1]);
}
finally {
disableSyncScrollSupport(false);
}
}
else {
DiffUtil.scrollToCaret(getCurrentEditor(), false);
}
return true;
}
private boolean doScrollToLine() {
@Override
protected boolean doScrollToLine() {
if (myScrollToLine == null) return false;
Side side = myScrollToLine.first;
Integer line = myScrollToLine.second;
if (side.select(myEditor1, myEditor2) == null) return false;
if (side.select(getEditors()) == null) return false;
myCurrentSide = side;
DiffUtil.scrollEditor(getCurrentEditor(), line, false);
scrollToLine(side, line);
return true;
}
}
@@ -30,6 +30,19 @@ import java.util.ArrayList;
import java.util.List;
public class DiffDividerDrawUtil {
/*
* Clip given graphics of divider component such that result graphics is aligned with base component by 'y' coordinate.
*/
@NotNull
public static Graphics2D getDividerGraphics(@NotNull Graphics g, @NotNull Component divider, @NotNull Component base) {
int width = divider.getWidth();
int editorHeight = base.getHeight();
int dividerOffset = divider.getLocationOnScreen().y;
int editorOffset = base.getLocationOnScreen().y;
return (Graphics2D)g.create(0, editorOffset - dividerOffset, width, editorHeight);
}
public static void paintSeparators(@NotNull Graphics2D gg,
int width,
@NotNull Editor editor1,
@@ -248,61 +248,6 @@ public class DiffUtil {
return editor != null ? editor.getCaretModel().getLogicalPosition() : new LogicalPosition(0, 0);
}
@NotNull
public static Point[] getScrollingPositions(@NotNull List<? extends Editor> editors) {
Point[] carets = new Point[editors.size()];
for (int i = 0; i < editors.size(); i++) {
carets[i] = getScrollingPosition(editors.get(i));
}
return carets;
}
@NotNull
public static LogicalPosition[] getCaretPositions(@NotNull List<? extends Editor> editors) {
LogicalPosition[] carets = new LogicalPosition[editors.size()];
for (int i = 0; i < editors.size(); i++) {
carets[i] = getCaretPosition(editors.get(i));
}
return carets;
}
public static boolean wasScrolled(@NotNull List<? extends Editor> editors) {
for (Editor editor : editors) {
if (editor == null) continue;
if (editor.getCaretModel().getOffset() != 0) return true;
if (editor.getScrollingModel().getVerticalScrollOffset() != 0) return true;
if (editor.getScrollingModel().getHorizontalScrollOffset() != 0) return true;
}
return false;
}
public static class EditorsVisiblePositions {
public static final Key<EditorsVisiblePositions> KEY = Key.create("Diff.EditorsVisiblePositions");
@NotNull public final LogicalPosition[] myCaretPosition;
@NotNull public final Point[] myPoints;
public EditorsVisiblePositions(@NotNull LogicalPosition caretPosition, @NotNull Point points) {
myCaretPosition = new LogicalPosition[]{caretPosition};
myPoints = new Point[]{points};
}
public EditorsVisiblePositions(@NotNull LogicalPosition[] caretPosition, @NotNull Point[] points) {
myCaretPosition = caretPosition;
myPoints = points;
}
public boolean isSame(@Nullable LogicalPosition... caretPosition) {
// TODO: allow small fluctuations ?
if (caretPosition == null) return true;
if (myCaretPosition.length != caretPosition.length) return false;
for (int i = 0; i < caretPosition.length; i++) {
if (!caretPosition[i].equals(myCaretPosition[i])) return false;
}
return true;
}
}
//
// UI
//
@@ -54,7 +54,7 @@ public class EditorTracker extends AbstractProjectComponent {
private final Map<Window, List<Editor>> myWindowToEditorsMap = new HashMap<Window, List<Editor>>();
private final Map<Window, WindowFocusListener> myWindowToWindowFocusListenerMap = new HashMap<Window, WindowFocusListener>();
private final Map<Editor, Window> myEditorToWindowMap = new HashMap<Editor, Window>();
private List<Editor> myActiveEditors = Collections.emptyList();
private List<Editor> myActiveEditors = Collections.emptyList(); // accessed in EDT only
private final EventDispatcher<EditorTrackerListener> myDispatcher = EventDispatcher.create(EditorTrackerListener.class);
@@ -186,7 +186,8 @@ public class EditorTracker extends AbstractProjectComponent {
}
@NotNull
public List<Editor> getActiveEditors() {
List<Editor> getActiveEditors() {
ApplicationManager.getApplication().assertIsDispatchThread();
return myActiveEditors;
}
@@ -210,6 +211,7 @@ public class EditorTracker extends AbstractProjectComponent {
}
void setActiveEditors(@NotNull List<Editor> editors) {
ApplicationManager.getApplication().assertIsDispatchThread();
myActiveEditors = editors;
if (LOG.isDebugEnabled()) {
@@ -479,6 +479,17 @@ public abstract class UsefulTestCase extends TestCase {
}
}
public static void assertOrderedEquals(@NotNull int[] actual, @NotNull int[] expected) {
if (actual.length != expected.length) {
fail("Expected size: "+expected.length+"; actual: "+actual.length+"\nexpected: "+Arrays.toString(expected)+"\nactual : "+Arrays.toString(actual));
}
for (int i = 0; i < actual.length; i++) {
int a = actual[i];
int e = expected[i];
assertEquals("not equals at index: "+i, e, a);
}
}
public static <T> void assertOrderedEquals(final String errorMsg, @NotNull Iterable<T> actual, @NotNull T... expected) {
Assert.assertNotNull(actual);
Assert.assertNotNull(expected);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* 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.
@@ -98,6 +98,22 @@ public class ArrayUtil extends ArrayUtilRt {
return result;
}
@NotNull
@Contract(pure=true)
public static long[] realloc(@NotNull long[] array, int newSize) {
if (newSize == 0) {
return EMPTY_LONG_ARRAY;
}
final int oldSize = array.length;
if (oldSize == newSize) {
return array;
}
long[] result = new long[newSize];
System.arraycopy(array, 0, result, 0, Math.min(oldSize, newSize));
return result;
}
@NotNull
@Contract(pure=true)
public static int[] realloc(@NotNull int[] array, final int newSize) {
@@ -131,6 +147,13 @@ public class ArrayUtil extends ArrayUtilRt {
return result;
}
@NotNull
@Contract(pure=true)
public static long[] append(@NotNull long[] array, long value) {
array = realloc(array, array.length + 1);
array[array.length - 1] = value;
return array;
}
@NotNull
@Contract(pure=true)
public static int[] append(@NotNull int[] array, int value) {
@@ -720,6 +743,14 @@ public class ArrayUtil extends ArrayUtilRt {
return -1;
}
@Contract(pure=true)
public static int indexOf(@NotNull long[] ints, long value) {
for (int i = 0; i < ints.length; i++) {
if (ints[i] == value) return i;
}
return -1;
}
@Contract(pure=true)
public static int indexOf(@NotNull int[] ints, int value) {
for (int i = 0; i < ints.length; i++) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* 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.
@@ -15,7 +15,6 @@
*/
package com.intellij.util;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.SingletonIterator;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
@@ -30,15 +29,9 @@ import java.util.Set;
*/
public class SingletonSet<E> implements Set<E> {
private final E theElement;
@NotNull private final TObjectHashingStrategy<E> strategy;
public SingletonSet(E e) {
this(e, ContainerUtil.<E>canonicalStrategy());
}
public SingletonSet(E e, @NotNull final TObjectHashingStrategy<E> strategy) {
theElement = e;
this.strategy = strategy;
}
@Override
@@ -48,7 +41,8 @@ public class SingletonSet<E> implements Set<E> {
@Override
public boolean contains(Object elem) {
return strategy.equals(theElement, (E)elem);
//noinspection unchecked
return getStrategy().equals(theElement, (E)elem);
}
@NotNull
@@ -67,8 +61,10 @@ public class SingletonSet<E> implements Set<E> {
@Override
public <T> T[] toArray(@NotNull T[] a) {
if (a.length == 0) {
//noinspection unchecked
a = (T[]) Array.newInstance(a.getClass().getComponentType(), 1);
}
//noinspection unchecked
a[0] = (T)theElement;
if (a.length > 1) {
a[1] = null;
@@ -120,4 +116,31 @@ public class SingletonSet<E> implements Set<E> {
public boolean isEmpty() {
return false;
}
@NotNull
protected TObjectHashingStrategy<E> getStrategy() {
//noinspection unchecked
return TObjectHashingStrategy.CANONICAL;
}
@NotNull
public static <T> Set<T> withCustomStrategy(T o, @NotNull TObjectHashingStrategy<T> strategy) {
return new CustomStrategySingletonSet<T>(o, strategy);
}
private static class CustomStrategySingletonSet<E> extends SingletonSet<E> {
@NotNull private final TObjectHashingStrategy<E> strategy;
private CustomStrategySingletonSet(E e, @NotNull final TObjectHashingStrategy<E> strategy) {
super(e);
this.strategy = strategy;
}
@Override
@NotNull
protected TObjectHashingStrategy<E> getStrategy() {
return strategy;
}
}
}
@@ -2101,7 +2101,7 @@ public class ContainerUtil extends ContainerUtilRt {
@NotNull
@Contract(pure=true)
public static <T> Set<T> singleton(final T o, @NotNull final TObjectHashingStrategy<T> strategy) {
return new SingletonSet<T>(o, strategy);
return strategy == TObjectHashingStrategy.CANONICAL ? new SingletonSet<T>(o) : SingletonSet.<T>withCustomStrategy(o, strategy);
}
/**
@@ -17,7 +17,9 @@
package com.intellij.util.containers;
import com.intellij.openapi.util.Condition;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ThrowableRunnable;
import gnu.trove.TIntArrayList;
import junit.framework.TestCase;
@@ -225,17 +227,21 @@ public class ContainerUtilTest extends TestCase {
}
}
public void testLockFreeCOWPerformanceIsAdequateForRegisteringAllIElementTypesReasonablyQuick() {
List<Object> my = ContainerUtil.createLockFreeCopyOnWriteList();
long start = System.currentTimeMillis();
// see IElementType.ourRegistry
for (int i = 0; i < 15000; i++) {
my.add(i);
assertEquals(i, my.indexOf(i));
}
long elapsed = System.currentTimeMillis() - start;
System.out.println("elapsed = " + elapsed);
assertTrue(String.valueOf(elapsed), elapsed < 1000);
public void testCOWListPerformanceIsAdequateForRegisteringAllIElementTypesReasonablyQuick() {
PlatformTestUtil.startPerformanceTest("COWList add", 1000, new ThrowableRunnable() {
@Override
public void run() throws Throwable {
List<Object> my = ContainerUtil.createLockFreeCopyOnWriteList();
long start = System.currentTimeMillis();
// see IElementType.ourRegistry
for (int i = 0; i < 15000; i++) {
my.add(i);
assertEquals(i, my.indexOf(i));
}
long elapsed = System.currentTimeMillis() - start;
System.out.println("elapsed = " + elapsed);
}
}).assertTiming();
}
private static void assertReallyEmpty(List<Object> my) {
+2 -2
View File
@@ -24,6 +24,7 @@
<orderEntry type="library" name="CGLIB" level="project" />
<orderEntry type="library" name="asm" level="project" />
<orderEntry type="library" exported="" name="ForkJoin" level="project" />
<orderEntry type="module" module-name="testFramework" scope="TEST" />
</component>
<component name="copyright">
<Base>
@@ -177,5 +178,4 @@
<option name="useAlternate" value="false" />
</LanguageOptions>
</component>
</module>
</module>
@@ -1,5 +1,6 @@
package com.intellij.openapi.vcs.changes.actions.migrate;
import com.intellij.diff.contents.FileContentImpl;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -22,7 +23,6 @@ import com.intellij.diff.chains.DiffRequestChain;
import com.intellij.diff.chains.DiffRequestProducer;
import com.intellij.diff.chains.DiffRequestProducerException;
import com.intellij.diff.chains.SimpleDiffRequestChain;
import com.intellij.diff.contents.BinaryFileContentImpl;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.contents.DocumentContentImpl;
import com.intellij.diff.contents.EmptyContent;
@@ -118,7 +118,7 @@ public class MigrateToNewDiffUtil {
if (oldContent.isBinary()) {
VirtualFile file = oldContent.getFile();
if (file == null) return null;
return new BinaryFileContentImpl(project, file);
return new FileContentImpl(project, file);
}
else {
Document document = oldContent.getDocument();
@@ -206,7 +206,7 @@ public class SvnPropertiesDiffViewer extends TwosideTextDiffViewer {
@Override
public void paint(@NotNull Graphics g, @NotNull JComponent divider) {
assert myEditor1 != null && myEditor2 != null;
Graphics2D gg = getDividerGraphics(g, divider);
Graphics2D gg = DiffDividerDrawUtil.getDividerGraphics(g, divider, getEditor1().getComponent());
Rectangle clip = gg.getClipBounds();
if (clip == null) return;