diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java index 1504b61d4aca..578c2f85ce1c 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java @@ -71,7 +71,7 @@ public class RefManagerImpl extends RefManager { private final Project myProject; private AnalysisScope myScope; private RefProject myRefProject; - private final ConcurrentMap myRefTable = ContainerUtil.newConcurrentMap(); + private final Map myRefTable = new THashMap(); // guarded by myRefTable private final ConcurrentMap 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 getSortedElements() { - List answer = new ArrayList(myRefTable.values()); + List answer; + synchronized (myRefTable) { + answer = new ArrayList(myRefTable.values()); + } ContainerUtil.quickSort(answer, new Comparator() { @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 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 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 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; diff --git a/platform/diff-api/src/com/intellij/diff/contents/BinaryFileContent.java b/platform/diff-api/src/com/intellij/diff/contents/BinaryFileContent.java index b65e55b01c81..600027f58507 100644 --- a/platform/diff-api/src/com/intellij/diff/contents/BinaryFileContent.java +++ b/platform/diff-api/src/com/intellij/diff/contents/BinaryFileContent.java @@ -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. diff --git a/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java index 8acca83b1b90..af73b7ecf550 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java @@ -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 diff --git a/platform/diff-impl/src/com/intellij/diff/actions/impl/OpenInEditorWithMouseAction.java b/platform/diff-impl/src/com/intellij/diff/actions/impl/OpenInEditorWithMouseAction.java index 81f55ece4fda..35bcd9f61a6c 100644 --- a/platform/diff-impl/src/com/intellij/diff/actions/impl/OpenInEditorWithMouseAction.java +++ b/platform/diff-impl/src/com/intellij/diff/actions/impl/OpenInEditorWithMouseAction.java @@ -42,6 +42,7 @@ public abstract class OpenInEditorWithMouseAction extends AnAction implements Du public void register(@NotNull List 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; } } diff --git a/platform/diff-impl/src/com/intellij/diff/actions/impl/SetEditorSettingsAction.java b/platform/diff-impl/src/com/intellij/diff/actions/impl/SetEditorSettingsAction.java index 1dcf1f000300..59b1ba668e7e 100644 --- a/platform/diff-impl/src/com/intellij/diff/actions/impl/SetEditorSettingsAction.java +++ b/platform/diff-impl/src/com/intellij/diff/actions/impl/SetEditorSettingsAction.java @@ -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 myEditors; @@ -125,7 +125,7 @@ public abstract class SetEditorSettingsAction extends ActionGroup implements Dum @Override public void applyDefaults(@NotNull List 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 editors) { for (Editor editor : editors) { + if (editor == null) continue; apply(editor, isSelected()); } } diff --git a/platform/diff-impl/src/com/intellij/diff/contents/BinaryFileContentImpl.java b/platform/diff-impl/src/com/intellij/diff/contents/FileContentImpl.java similarity index 90% rename from platform/diff-impl/src/com/intellij/diff/contents/BinaryFileContentImpl.java rename to platform/diff-impl/src/com/intellij/diff/contents/FileContentImpl.java index 155e3fd27bc2..cf458199e8c9 100644 --- a/platform/diff-impl/src/com/intellij/diff/contents/BinaryFileContentImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/contents/FileContentImpl.java @@ -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; diff --git a/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffPanel.java b/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffPanel.java deleted file mode 100644 index b0da942bff45..000000000000 --- a/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffPanel.java +++ /dev/null @@ -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(); - } -} diff --git a/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffViewer.java index 877a6bbe23a3..9079242200e0 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffViewer.java @@ -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 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() { + @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; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java index a4dd1e76416f..da228f70dbc8 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java @@ -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; } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffPanel.java b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffPanel.java index ed398dc7b7fd..493c4c494f97 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffPanel.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffPanel.java @@ -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; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java index 4146860c90f5..652904780f43 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java @@ -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 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 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; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffChange.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffChange.java index 03ee0355ca4a..6ebca07a36ba 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffChange.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffChange.java @@ -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()); } }); } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java index 0999e124be64..4f007437da89 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java @@ -77,6 +77,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer { @NotNull private final List myInvalidDiffChanges = new ArrayList(); @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 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 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 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; + } + } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java index 5fe13fabbd4d..7820a0e6dbe2 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java @@ -73,6 +73,7 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer { @NotNull private final List myInvalidDiffChanges = new ArrayList(); @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; + } + } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffNotifications.java b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffNotifications.java new file mode 100644 index 000000000000..1d5f6565baea --- /dev/null +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffNotifications.java @@ -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); + } +} diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/EditorsDiffPanelBase.java b/platform/diff-impl/src/com/intellij/diff/tools/util/SimpleDiffPanel.java similarity index 76% rename from platform/diff-impl/src/com/intellij/diff/tools/util/EditorsDiffPanelBase.java rename to platform/diff-impl/src/com/intellij/diff/tools/util/SimpleDiffPanel.java index d4cb95b84fee..fd498a4a070f 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/EditorsDiffPanelBase.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/SimpleDiffPanel.java @@ -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(); } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/StatusPanel.java b/platform/diff-impl/src/com/intellij/diff/tools/util/StatusPanel.java index 2fe2db5fd8aa..1f55eb4d6094 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/StatusPanel.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/StatusPanel.java @@ -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)); } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/SyncScrollSupport.java b/platform/diff-impl/src/com/intellij/diff/tools/util/SyncScrollSupport.java index 3ae8591b103e..5a97124251b8 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/SyncScrollSupport.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/SyncScrollSupport.java @@ -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 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 { diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/DiffPanelBase.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/DiffPanelBase.java index 4a87aa5fc675..faaf09f7cb71 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/DiffPanelBase.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/DiffPanelBase.java @@ -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(); } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/DiffViewerBase.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/DiffViewerBase.java index 8e03481e1c7a..5f41070aa91f 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/DiffViewerBase.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/DiffViewerBase.java @@ -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 diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/InitialScrollPositionSupport.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/InitialScrollPositionSupport.java new file mode 100644 index 000000000000..83d1f0af4fe7 --- /dev/null +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/InitialScrollPositionSupport.java @@ -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 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 getEditors(); + + protected abstract void disableSyncScroll(boolean value); + } + + public static abstract class TwosideInitialScrollHelper extends SideInitialScrollHelper { + @Nullable protected Pair 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 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 getEditors(); + } + + @NotNull + public static Point[] doGetScrollingPositions(@NotNull List 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 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 editors) { + LogicalPosition[] carets = doGetCaretPositions(editors); + Point[] points = doGetScrollingPositions(editors); + return new EditorsVisiblePositions(carets, points); + } + + public static void doMoveCaretsToPositions(@NotNull LogicalPosition[] positions, @NotNull List 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 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 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 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 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; + } + } +} diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/ListenerDiffViewerBase.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/ListenerDiffViewerBase.java index 45cc5114a85c..d6385862296c 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/ListenerDiffViewerBase.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/ListenerDiffViewerBase.java @@ -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 files = new ArrayList(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()); } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffPanel.java b/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffPanel.java deleted file mode 100644 index 32d44d3a3a11..000000000000 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffPanel.java +++ /dev/null @@ -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(); - } -} diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java index a493a09b9e10..a1f81110d4d1 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java @@ -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 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 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 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; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffPanel.java b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffPanel.java deleted file mode 100644 index 2b08d6d7767c..000000000000 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffPanel.java +++ /dev/null @@ -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(); - } -} diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java index 9b41da572566..0a767ff45e5e 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java @@ -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 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 getEditors() { + return TwosideTextDiffViewer.this.getEditors(); } - public void updateContext() { - List 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; } } diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffDividerDrawUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffDividerDrawUtil.java index 47355b91adc2..9fe5e8e88d3c 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffDividerDrawUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffDividerDrawUtil.java @@ -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, diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java index cc0e0d50959b..1037d5e53e13 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java @@ -248,61 +248,6 @@ public class DiffUtil { return editor != null ? editor.getCaretModel().getLogicalPosition() : new LogicalPosition(0, 0); } - @NotNull - public static Point[] getScrollingPositions(@NotNull List 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 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 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 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 // diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/EditorTracker.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/EditorTracker.java index 628de696a061..b43099cc2f75 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/EditorTracker.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/EditorTracker.java @@ -54,7 +54,7 @@ public class EditorTracker extends AbstractProjectComponent { private final Map> myWindowToEditorsMap = new HashMap>(); private final Map myWindowToWindowFocusListenerMap = new HashMap(); private final Map myEditorToWindowMap = new HashMap(); - private List myActiveEditors = Collections.emptyList(); + private List myActiveEditors = Collections.emptyList(); // accessed in EDT only private final EventDispatcher myDispatcher = EventDispatcher.create(EditorTrackerListener.class); @@ -186,7 +186,8 @@ public class EditorTracker extends AbstractProjectComponent { } @NotNull - public List getActiveEditors() { + List getActiveEditors() { + ApplicationManager.getApplication().assertIsDispatchThread(); return myActiveEditors; } @@ -210,6 +211,7 @@ public class EditorTracker extends AbstractProjectComponent { } void setActiveEditors(@NotNull List editors) { + ApplicationManager.getApplication().assertIsDispatchThread(); myActiveEditors = editors; if (LOG.isDebugEnabled()) { diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 831507731a7d..fec7abf3a2bc 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -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 void assertOrderedEquals(final String errorMsg, @NotNull Iterable actual, @NotNull T... expected) { Assert.assertNotNull(actual); Assert.assertNotNull(expected); diff --git a/platform/util/src/com/intellij/util/ArrayUtil.java b/platform/util/src/com/intellij/util/ArrayUtil.java index 36a19f6f4bf2..462f90c86447 100644 --- a/platform/util/src/com/intellij/util/ArrayUtil.java +++ b/platform/util/src/com/intellij/util/ArrayUtil.java @@ -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++) { diff --git a/platform/util/src/com/intellij/util/SingletonSet.java b/platform/util/src/com/intellij/util/SingletonSet.java index 19aa96be2b21..d289424a4e16 100644 --- a/platform/util/src/com/intellij/util/SingletonSet.java +++ b/platform/util/src/com/intellij/util/SingletonSet.java @@ -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 implements Set { private final E theElement; - @NotNull private final TObjectHashingStrategy strategy; public SingletonSet(E e) { - this(e, ContainerUtil.canonicalStrategy()); - } - - public SingletonSet(E e, @NotNull final TObjectHashingStrategy strategy) { theElement = e; - this.strategy = strategy; } @Override @@ -48,7 +41,8 @@ public class SingletonSet implements Set { @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 implements Set { @Override public 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 implements Set { public boolean isEmpty() { return false; } + + @NotNull + protected TObjectHashingStrategy getStrategy() { + //noinspection unchecked + return TObjectHashingStrategy.CANONICAL; + } + + @NotNull + public static Set withCustomStrategy(T o, @NotNull TObjectHashingStrategy strategy) { + return new CustomStrategySingletonSet(o, strategy); + } + + private static class CustomStrategySingletonSet extends SingletonSet { + @NotNull private final TObjectHashingStrategy strategy; + + private CustomStrategySingletonSet(E e, @NotNull final TObjectHashingStrategy strategy) { + super(e); + this.strategy = strategy; + } + + + @Override + @NotNull + protected TObjectHashingStrategy getStrategy() { + return strategy; + } + } } diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index abcbd941d6d7..634e81ad8990 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -2101,7 +2101,7 @@ public class ContainerUtil extends ContainerUtilRt { @NotNull @Contract(pure=true) public static Set singleton(final T o, @NotNull final TObjectHashingStrategy strategy) { - return new SingletonSet(o, strategy); + return strategy == TObjectHashingStrategy.CANONICAL ? new SingletonSet(o) : SingletonSet.withCustomStrategy(o, strategy); } /** diff --git a/platform/util/testSrc/com/intellij/util/containers/ContainerUtilTest.java b/platform/util/testSrc/com/intellij/util/containers/ContainerUtilTest.java index 45a299881434..941e5fd534ba 100644 --- a/platform/util/testSrc/com/intellij/util/containers/ContainerUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/containers/ContainerUtilTest.java @@ -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 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 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 my) { diff --git a/platform/util/util.iml b/platform/util/util.iml index c015e73f13b3..684449e02d43 100644 --- a/platform/util/util.iml +++ b/platform/util/util.iml @@ -24,6 +24,7 @@ + @@ -177,5 +178,4 @@ - - + \ No newline at end of file diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/migrate/MigrateToNewDiffUtil.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/migrate/MigrateToNewDiffUtil.java index 2c69ab6725c6..bacab1d07f6e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/migrate/MigrateToNewDiffUtil.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/migrate/MigrateToNewDiffUtil.java @@ -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(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffViewer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffViewer.java index 7643b85c98a3..eb5ed3e0f8b0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffViewer.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffViewer.java @@ -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;