diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index 67457f687fed..33613c4765d8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -39,6 +39,7 @@ import com.intellij.openapi.diff.impl.util.*; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollingModel; +import com.intellij.openapi.editor.event.VisibleAreaEvent; import com.intellij.openapi.editor.event.VisibleAreaListener; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.EditorGutterComponentEx; @@ -104,6 +105,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid private final boolean myIsHorisontal; private CanNotCalculateDiffPanel myNotCalculateDiffPanel; private DiffIsApproximate myDiffIsApproximate; + private final VisibleAreaListener myVisibleAreaListener; public DiffPanelImpl(final Window owner, Project project, boolean enableToolbar, boolean horisontal) { myProject = project; @@ -139,6 +141,19 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid if (defaultComparisonPolicy != null && comparisonPolicy != defaultComparisonPolicy) { setComparisonPolicy(defaultComparisonPolicy); } + myVisibleAreaListener = new VisibleAreaListener() { + @Override + public void visibleAreaChanged(VisibleAreaEvent e) { + Editor editor1 = getEditor1(); + if (editor1 != null) { + editor1.getComponent().repaint(); + } + Editor editor2 = getEditor2(); + if (editor2 != null) { + editor2.getComponent().repaint(); + } + } + }; } protected DiffPanelState createDiffPanelState(@NotNull Disposable parentDisposable) { @@ -391,6 +406,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid final ScrollingModel scrollingModel = editor.getScrollingModel(); if (visibleAreaListener != null) { scrollingModel.addVisibleAreaListener(visibleAreaListener); + scrollingModel.addVisibleAreaListener(myVisibleAreaListener); } myFontSizeSynchronizer.synchronize(editor); source.addDisposable(new Disposable() { @@ -402,6 +418,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid public void dispose() { if (visibleAreaListener != null) { scrollingModel.removeVisibleAreaListener(visibleAreaListener); + scrollingModel.removeVisibleAreaListener(myVisibleAreaListener); } editor.getContentComponent().removeMouseListener(mouseListener); } diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java index 4233400a1ee5..2604da35f53f 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java @@ -46,10 +46,7 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileFilter; -import com.intellij.util.Alarm; -import com.intellij.util.ArrayUtil; -import com.intellij.util.SystemProperties; -import com.intellij.util.ThrowableRunnable; +import com.intellij.util.*; import com.intellij.util.containers.HashMap; import com.intellij.util.io.ZipUtil; import com.intellij.util.ui.UIUtil; @@ -120,13 +117,27 @@ public class PlatformTestUtil { public static String print(JTree tree, boolean withSelection, Condition nodePrintCondition) { StringBuilder buffer = new StringBuilder(); - Object root = tree.getModel().getRoot(); - printImpl(tree, root, buffer, 0, withSelection, nodePrintCondition); + + final Collection strings = printAsList(tree, withSelection, nodePrintCondition); + for (String string : strings) { + buffer.append(string).append("\n"); + } return buffer.toString(); } - - private static void printImpl(JTree tree, Object root, StringBuilder buffer, int level, boolean withSelection, @Nullable Condition nodePrintCondition) { + public static Collection printAsList(JTree tree, boolean withSelection, Condition nodePrintCondition) { + Collection strings = new ArrayList(); + Object root = tree.getModel().getRoot(); + printImpl(tree, root, strings, 0, withSelection, nodePrintCondition); + return strings; + } + + private static void printImpl(JTree tree, + Object root, + Collection strings, + int level, + boolean withSelection, + @Nullable Condition nodePrintCondition) { DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode)root; @@ -143,34 +154,42 @@ public class PlatformTestUtil { if (nodePrintCondition != null && !nodePrintCondition.value(nodeText)) return; boolean expanded = tree.isExpanded(new TreePath(defaultMutableTreeNode.getPath())); - StringUtil.repeatSymbol(buffer, ' ', level); - if (expanded && !defaultMutableTreeNode.isLeaf()) { - buffer.append("-"); - } - if (!expanded && !defaultMutableTreeNode.isLeaf()) { - buffer.append("+"); - } - - final boolean selected = tree.getSelectionModel().isPathSelected(new TreePath(defaultMutableTreeNode.getPath())); - - if (withSelection && selected) { - buffer.append("["); - } - - - buffer.append(nodeText); - - if (withSelection && selected) { - buffer.append("]"); - } - - buffer.append("\n"); - int childCount = tree.getModel().getChildCount(root); - if (expanded) { - for (int i = 0; i < childCount; i++) { - printImpl(tree, tree.getModel().getChild(root, i), buffer, level + 1, withSelection, nodePrintCondition); + final StringBuilder buff = StringBuilderSpinAllocator.alloc(); + try { + StringUtil.repeatSymbol(buff, ' ', level); + if (expanded && !defaultMutableTreeNode.isLeaf()) { + buff.append("-"); } + + if (!expanded && !defaultMutableTreeNode.isLeaf()) { + buff.append("+"); + } + + final boolean selected = tree.getSelectionModel().isPathSelected(new TreePath(defaultMutableTreeNode.getPath())); + + if (withSelection && selected) { + buff.append("["); + } + + + buff.append(nodeText); + + if (withSelection && selected) { + buff.append("]"); + } + + //buff.append("\n"); + strings.add(buff.toString()); + + int childCount = tree.getModel().getChildCount(root); + if (expanded) { + for (int i = 0; i < childCount; i++) { + printImpl(tree, tree.getModel().getChild(root, i), strings, level + 1, withSelection, nodePrintCondition); + } + } + } finally { + StringBuilderSpinAllocator.dispose(buff); } } @@ -178,11 +197,21 @@ public class PlatformTestUtil { assertTreeEqual(tree, expected, false); } + public static void assertTreeEqualIgnoringNodesOrder(JTree tree, @NonNls String expected) { + assertTreeEqualIgnoringNodesOrder(tree, expected, false); + } + public static void assertTreeEqual(JTree tree, String expected, boolean checkSelected) { String treeStringPresentation = print(tree, checkSelected); Assert.assertEquals(expected, treeStringPresentation); } + public static void assertTreeEqualIgnoringNodesOrder(JTree tree, String expected, boolean checkSelected) { + final Collection actualNodesPresentation = printAsList(tree, checkSelected, null); + final List expectedNodes = StringUtil.split(expected, "\n"); + UsefulTestCase.assertSameElements(actualNodesPresentation, expectedNodes); + } + @TestOnly public static void waitForAlarm(final int delay) throws InterruptedException { assert !ApplicationManager.getApplication().isWriteAccessAllowed(): "It's a bad idea to wait for an alarm under the write action. Somebody creates an alarm which requires read action and you are deadlocked.";