diff: improve javadoc for DiffRequestChain
[idea/community.git] / platform / vcs-impl / src / com / intellij / openapi / vcs / changes / ui / ChangeDiffRequestChain.java
1 // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.openapi.vcs.changes.ui;
3
4 import com.intellij.diff.actions.impl.GoToChangePopupBuilder;
5 import com.intellij.diff.chains.AsyncDiffRequestChain;
6 import com.intellij.diff.chains.DiffRequestProducer;
7 import com.intellij.diff.chains.DiffRequestProducerException;
8 import com.intellij.diff.chains.DiffRequestSelectionChain;
9 import com.intellij.openapi.ListSelection;
10 import com.intellij.openapi.actionSystem.AnAction;
11 import com.intellij.openapi.diagnostic.Logger;
12 import com.intellij.openapi.util.Conditions;
13 import com.intellij.openapi.util.UserDataHolderBase;
14 import com.intellij.openapi.vcs.changes.actions.diff.PresentableGoToChangePopupAction;
15 import com.intellij.util.Consumer;
16 import com.intellij.util.ObjectUtils;
17 import com.intellij.util.containers.ContainerUtil;
18 import org.jetbrains.annotations.NotNull;
19 import org.jetbrains.annotations.Nullable;
20
21 import java.util.ArrayList;
22 import java.util.List;
23
24 /**
25  * Supports typical tree-like "Go to Change" navigation popup.
26  *
27  * @see ChangeDiffRequestChain.Async
28  */
29 public class ChangeDiffRequestChain extends UserDataHolderBase implements DiffRequestSelectionChain, GoToChangePopupBuilder.Chain {
30   private static final Logger LOG = Logger.getInstance(ChangeDiffRequestChain.class);
31   @NotNull private final ListSelection<? extends Producer> myProducers;
32
33   public ChangeDiffRequestChain(@NotNull ListSelection<? extends Producer> producers) {
34     myProducers = producers.map(it -> {
35       if (it == null) LOG.error("Producers must not be null");
36       return it;
37     });
38   }
39
40   public ChangeDiffRequestChain(@NotNull List<? extends Producer> producers, int index) {
41     this(ListSelection.createAt(producers, index));
42   }
43
44   @Override
45   public @NotNull ListSelection<? extends Producer> getListSelection() {
46     return myProducers;
47   }
48
49   @Override
50   @NotNull
51   public List<? extends Producer> getRequests() {
52     return myProducers.getList();
53   }
54
55   @NotNull
56   @Override
57   public AnAction createGoToChangeAction(@NotNull Consumer<? super Integer> onSelected, int defaultSelection) {
58     return createGoToChangeAction(getRequests(), onSelected, defaultSelection);
59   }
60
61   @NotNull
62   private static AnAction createGoToChangeAction(@NotNull List<? extends Producer> producers,
63                                                  @NotNull Consumer<? super Integer> onSelected,
64                                                  int defaultSelection) {
65     return new PresentableGoToChangePopupAction<ProducerWrapper>() {
66       @Override
67       protected @NotNull ListSelection<? extends ProducerWrapper> getChanges() {
68         List<ProducerWrapper> wrappers = new ArrayList<>();
69         for (int i = 0; i < producers.size(); i++) {
70           wrappers.add(new ProducerWrapper(producers.get(i), i));
71         }
72         return ListSelection.createAt(wrappers, defaultSelection);
73       }
74
75       @Override
76       protected PresentableChange getPresentation(@NotNull ProducerWrapper change) {
77         return change.producer;
78       }
79
80       @Override
81       protected void onSelected(@NotNull ProducerWrapper change) {
82         onSelected.consume(change.index);
83       }
84     };
85   }
86
87   private static class ProducerWrapper {
88     public final @NotNull Producer producer;
89     public final int index;
90
91     private ProducerWrapper(@NotNull Producer producer, int index) {
92       this.producer = producer;
93       this.index = index;
94     }
95   }
96
97   public interface Producer extends DiffRequestProducer, PresentableChange {
98   }
99
100   public static abstract class Async extends AsyncDiffRequestChain implements GoToChangePopupBuilder.Chain {
101     @NotNull
102     @Override
103     protected abstract ListSelection<? extends Producer> loadRequestProducers() throws DiffRequestProducerException;
104
105     @Nullable
106     @Override
107     public AnAction createGoToChangeAction(@NotNull Consumer<? super Integer> onSelected, int defaultSelection) {
108       List<? extends DiffRequestProducer> requests = getRequests();
109
110       // may contain other producers with intermediate MessageDiffRequest
111       List<Producer> producers = ContainerUtil.map(requests, it -> ObjectUtils.tryCast(it, Producer.class));
112       if (!ContainerUtil.all(producers, Conditions.notNull())) return null;
113
114       return ChangeDiffRequestChain.createGoToChangeAction(producers, onSelected, defaultSelection);
115     }
116   }
117 }