diff: show chain of diff requests for "Compare With Local" action with single selecte...
authorAleksey Pivovarov <AMPivovarov@gmail.com>
Tue, 11 Aug 2015 14:23:34 +0000 (17:23 +0300)
committerAleksey Pivovarov <AMPivovarov@gmail.com>
Tue, 1 Sep 2015 16:26:09 +0000 (19:26 +0300)
platform/platform-resources/src/META-INF/VcsExtensions.xml
platform/vcs-api/src/com/intellij/openapi/vcs/VcsDataKeys.java
platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangesSelection.java [new file with mode: 0644]
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangesSelectionRule.java [new file with mode: 0644]
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffWithLocalAction.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/ShowDiffAction.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowser.java

index d07e6da2c25211073bc71da0810b234bdf0ef9bb..591c81aba4c2c088a7a65735ee71748f6b945638 100644 (file)
@@ -70,6 +70,7 @@
     <projectSetProcessor implementation="com.intellij.openapi.vcs.OpenProjectSetProcessor"/>
 
     <getDataRule key="VCS_REVISION_NUMBERS" implementationClass="com.intellij.openapi.vcs.history.VcsRevisionNumberArrayRule"/>
+    <getDataRule key="vcs.ChangesSelection" implementationClass="com.intellij.openapi.vcs.changes.VcsChangesSelectionRule"/>
     <jbProtocolCommand implementation="com.intellij.openapi.vcs.checkout.JBProtocolCheckoutCommand"/>
   </extensions>
 </idea-plugin>
index dc1a4bd46087eca121a634fa4893edcf9a0254ab..0b23eb57e9ac36016b8ffef211270a58707ac5bb 100644 (file)
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.vcs.changes.Change;
 import com.intellij.openapi.vcs.changes.ChangeList;
 import com.intellij.openapi.vcs.changes.ChangeRequestChain;
+import com.intellij.openapi.vcs.changes.ChangesSelection;
 import com.intellij.openapi.vcs.history.VcsFileRevision;
 import com.intellij.openapi.vcs.history.VcsHistoryProvider;
 import com.intellij.openapi.vcs.history.VcsHistorySession;
@@ -51,6 +52,7 @@ public interface VcsDataKeys {
   DataKey<ChangeList[]> CHANGE_LISTS = DataKey.create("vcs.ChangeList");
   DataKey<Change> CURRENT_CHANGE = DataKey.create("vcs.CurrentChange");
   DataKey<Change[]> CHANGES = DataKey.create("vcs.Change");
+  DataKey<ChangesSelection> CHANGES_SELECTION = DataKey.create("vcs.ChangesSelection");
   DataKey<Change[]> CHANGES_WITH_MOVED_CHILDREN = DataKey.create("ChangeListView.ChangesWithDetails");
   DataKey<Change[]> SELECTED_CHANGES_IN_DETAILS = DataKey.create("ChangeListView.SelectedChangesWithMovedSubtrees");
   @NonNls DataKey<List<Change>> CHANGES_IN_LIST_KEY = DataKey.create("ChangeListView.ChangesInList");
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangesSelection.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangesSelection.java
new file mode 100644 (file)
index 0000000..b48c1e2
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.openapi.vcs.changes;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class ChangesSelection {
+  @NotNull private final List<Change> myChanges;
+  private final int myIndex;
+
+  public ChangesSelection(@NotNull List<Change> changes, int index) {
+    myChanges = changes;
+    myIndex = index;
+  }
+
+  @NotNull
+  public List<Change> getChanges() {
+    return myChanges;
+  }
+
+  public int getIndex() {
+    return myIndex;
+  }
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangesSelectionRule.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangesSelectionRule.java
new file mode 100644 (file)
index 0000000..31ea74a
--- /dev/null
@@ -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.openapi.vcs.changes;
+
+import com.intellij.ide.impl.dataRules.GetDataRule;
+import com.intellij.openapi.actionSystem.DataProvider;
+import com.intellij.openapi.vcs.VcsDataKeys;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+public class VcsChangesSelectionRule implements GetDataRule {
+  @Nullable
+  @Override
+  public Object getData(DataProvider dataProvider) {
+    return getChangesSelection(dataProvider);
+  }
+
+  @Nullable
+  public ChangesSelection getChangesSelection(@NotNull DataProvider dataProvider) {
+    Change currentChange = VcsDataKeys.CURRENT_CHANGE.getData(dataProvider);
+
+    Change[] selectedChanges = VcsDataKeys.SELECTED_CHANGES.getData(dataProvider);
+    if (selectedChanges != null) {
+      int index = Math.max(ArrayUtil.indexOf(selectedChanges, currentChange), 0);
+      return new ChangesSelection(Arrays.asList(selectedChanges), index);
+    }
+
+    Change[] changes = VcsDataKeys.CHANGES.getData(dataProvider);
+    if (changes != null) {
+      int index = Math.max(ArrayUtil.indexOf(changes, currentChange), 0);
+      return new ChangesSelection(Arrays.asList(changes), index);
+    }
+
+    if (currentChange != null) {
+      return new ChangesSelection(Collections.singletonList(currentChange), 0);
+    }
+    return null;
+  }
+}
index cb85ca2fd0bb3f13cc4a5c30ad673c5d45242ed3..60004759d2be43c32c87173ae067c4979c11ecd2 100644 (file)
@@ -19,21 +19,19 @@ import com.intellij.icons.AllIcons;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.project.DumbAware;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vcs.VcsBundle;
 import com.intellij.openapi.vcs.VcsDataKeys;
-import com.intellij.openapi.vcs.changes.Change;
-import com.intellij.openapi.vcs.changes.ChangeListManager;
-import com.intellij.openapi.vcs.changes.ContentRevision;
-import com.intellij.openapi.vcs.changes.CurrentContentRevision;
+import com.intellij.openapi.vcs.changes.*;
 import com.intellij.openapi.vcs.changes.committed.CommittedChangesBrowserUseCase;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.intellij.openapi.vcs.changes.actions.diff.ShowDiffAction.*;
+import static com.intellij.openapi.vcs.changes.actions.diff.ShowDiffAction.showDiffForChange;
 
 /**
  * @author yole
@@ -48,36 +46,36 @@ public class ShowDiffWithLocalAction extends AnAction implements DumbAware {
   public void actionPerformed(AnActionEvent e) {
     Project project = e.getData(CommonDataKeys.PROJECT);
     if (ChangeListManager.getInstance(project).isFreezedWithNotification(null)) return;
-    Change[] changes = e.getData(VcsDataKeys.CHANGES);
-    assert changes != null;
+    ChangesSelection selection = e.getRequiredData(VcsDataKeys.CHANGES_SELECTION);
+
+    int index = 0;
     List<Change> changesToLocal = new ArrayList<Change>();
-    for(Change change: changes) {
-      ContentRevision afterRevision = change.getAfterRevision();
+    for (int i = 0; i < selection.getChanges().size(); i++) {
+      if (i == selection.getIndex()) index = changesToLocal.size();
+      ContentRevision afterRevision = selection.getChanges().get(i).getAfterRevision();
       if (afterRevision != null && isValidAfterRevision(afterRevision)) {
         changesToLocal.add(new Change(afterRevision, CurrentContentRevision.create(afterRevision.getFile())));
       }
     }
     if (!changesToLocal.isEmpty()) {
-      showDiffForChange(project, changesToLocal, 0);
+      showDiffForChange(project, changesToLocal, index);
     }
   }
 
   public void update(final AnActionEvent e) {
     Project project = e.getData(CommonDataKeys.PROJECT);
-    Change[] changes = e.getData(VcsDataKeys.CHANGES);
+    ChangesSelection selection = e.getData(VcsDataKeys.CHANGES_SELECTION);
+    boolean isInAir = CommittedChangesBrowserUseCase.IN_AIR.equals(CommittedChangesBrowserUseCase.DATA_KEY.getData(e.getDataContext()));
 
-    e.getPresentation().setEnabled(project != null && changes != null &&
-                                   (! CommittedChangesBrowserUseCase.IN_AIR
-                                     .equals(CommittedChangesBrowserUseCase.DATA_KEY.getData(e.getDataContext()))) &&
-                                   anyHasAfterRevision(changes));
+    e.getPresentation().setEnabled(project != null && selection != null && !isInAir && anyHasAfterRevision(selection.getChanges()));
   }
 
-  private static boolean isValidAfterRevision(final ContentRevision afterRevision) {
+  private static boolean isValidAfterRevision(@Nullable final ContentRevision afterRevision) {
     return afterRevision != null && !afterRevision.getFile().isNonLocal() && !afterRevision.getFile().isDirectory();
   }
 
-  private static boolean anyHasAfterRevision(final Change[] changes) {
-    for(Change c: changes) {
+  private static boolean anyHasAfterRevision(@NotNull final List<Change> changes) {
+    for (Change c : changes) {
       if (isValidAfterRevision(c.getAfterRevision())) {
         return true;
       }
index f9577dfc2e13fb12e1526bb57f48cab3907b1fc3..55bec3ec9451190f9e4a4564be9426b04d0c0286 100644 (file)
@@ -39,6 +39,7 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -65,7 +66,11 @@ public class ShowDiffAction extends AnAction implements DumbAware {
   }
 
   protected static boolean canShowDiff(@Nullable Project project, @Nullable Change[] changes) {
-    if (changes == null || changes.length == 0) return false;
+    return changes != null && canShowDiff(project, Arrays.asList(changes));
+  }
+
+  protected static boolean canShowDiff(@Nullable Project project, @Nullable List<Change> changes) {
+    if (changes == null || changes.size() == 0) return false;
     for (Change change : changes) {
       if (ChangeDiffRequestProducer.canCreate(project, change)) return true;
     }
index 86c5823e7e4bef20ae9ca3865057c0b998f20e47..c3fde0ff15151da4c1070af39c61c662abecdd3f 100644 (file)
  */
 package com.intellij.openapi.vcs.changes.ui;
 
+import com.intellij.diff.DiffDialogHints;
+import com.intellij.diff.util.DiffUserDataKeysEx;
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.actionSystem.ex.CheckboxAction;
 import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
-import com.intellij.diff.DiffDialogHints;
-import com.intellij.diff.util.DiffUserDataKeysEx;
 import com.intellij.openapi.vcs.FilePath;
 import com.intellij.openapi.vcs.VcsBundle;
 import com.intellij.openapi.vcs.VcsDataKeys;
@@ -129,7 +129,7 @@ public class ChangesBrowser extends JPanel implements TypeSafeDataProvider {
   protected Runnable getDoubleClickHandler() {
     return new Runnable() {
       public void run() {
-        showDiff();
+        showDiff(getChangesSelection());
       }
     };
   }
@@ -182,7 +182,10 @@ public class ChangesBrowser extends JPanel implements TypeSafeDataProvider {
     if (key == VcsDataKeys.CHANGES) {
       List<Change> list = myViewer.getSelectedChanges();
       if (list.isEmpty()) list = myViewer.getChanges();
-      sink.put(VcsDataKeys.CHANGES, list.toArray(new Change [list.size()]));
+      sink.put(VcsDataKeys.CHANGES, list.toArray(new Change[list.size()]));
+    }
+    else if (key == VcsDataKeys.CHANGES_SELECTION) {
+      sink.put(VcsDataKeys.CHANGES_SELECTION, getChangesSelection());
     }
     else if (key == VcsDataKeys.CHANGE_LISTS) {
       sink.put(VcsDataKeys.CHANGE_LISTS, getSelectedChangeLists());
@@ -260,30 +263,39 @@ public class ChangesBrowser extends JPanel implements TypeSafeDataProvider {
   protected void updateDiffContext(@NotNull ShowDiffContext context) {
   }
 
-  private void showDiff() {
+  private void showDiff(@NotNull ChangesSelection selection) {
+    List<Change> changes = selection.getChanges();
+
+    Change[] changesArray = changes.toArray(new Change[changes.size()]);
+    showDiffForChanges(changesArray, selection.getIndex());
+
+    afterDiffRefresh();
+  }
+
+  @NotNull
+  protected ChangesSelection getChangesSelection() {
     final Change leadSelection = myViewer.getLeadSelection();
     List<Change> changes = myViewer.getSelectedChanges();
 
     if (changes.size() < 2) {
-      changes = myViewer.getChanges();
+      List<Change> allChanges = myViewer.getChanges();
+      if (allChanges.size() > 1) {
+        changes = allChanges;
+      }
     }
 
-    Change[] changesArray = changes.toArray(new Change[changes.size()]);
-
     if (leadSelection != null) {
       int indexInSelection = changes.indexOf(leadSelection);
       if (indexInSelection == -1) {
-        showDiffForChanges(new Change[]{leadSelection}, 0);
+        return new ChangesSelection(Collections.singletonList(leadSelection), 0);
       }
       else {
-        showDiffForChanges(changesArray, indexInSelection);
+        return new ChangesSelection(changes, indexInSelection);
       }
     }
     else {
-      showDiffForChanges(changesArray, 0);
+      return new ChangesSelection(changes, 0);
     }
-
-    afterDiffRefresh();
   }
 
   protected void afterDiffRefresh() {
@@ -328,12 +340,12 @@ public class ChangesBrowser extends JPanel implements TypeSafeDataProvider {
   protected void buildToolBar(final DefaultActionGroup toolBarGroup) {
     myDiffAction = new ShowDiffAction() {
       public void update(AnActionEvent e) {
-        Change[] changes = e.getData(VcsDataKeys.CHANGES);
-        e.getPresentation().setEnabled(canShowDiff(myProject, changes));
+        ChangesSelection selection = e.getData(VcsDataKeys.CHANGES_SELECTION);
+        e.getPresentation().setEnabled(selection != null && canShowDiff(myProject, selection.getChanges()));
       }
 
       public void actionPerformed(AnActionEvent e) {
-        showDiff();                     // todo here
+        showDiff(e.getRequiredData(VcsDataKeys.CHANGES_SELECTION));
       }
     };
     myDiffAction.registerCustomShortcutSet(CommonShortcuts.getDiff(), myViewer);