1 // Copyright 2000-2020 JetBrains s.r.o. 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.diff.chains;
4 import com.intellij.diff.chains.SimpleDiffRequestChain.DiffRequestProducerWrapper;
5 import com.intellij.diff.requests.ErrorDiffRequest;
6 import com.intellij.diff.requests.LoadingDiffRequest;
7 import com.intellij.openapi.Disposable;
8 import com.intellij.openapi.ListSelection;
9 import com.intellij.openapi.progress.ProgressIndicator;
10 import com.intellij.openapi.progress.util.BackgroundTaskUtil;
11 import com.intellij.openapi.util.UserDataHolderBase;
12 import com.intellij.util.EventDispatcher;
13 import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
14 import com.intellij.util.concurrency.annotations.RequiresEdt;
15 import org.jetbrains.annotations.NotNull;
16 import org.jetbrains.annotations.Nullable;
18 import java.util.EventListener;
20 public abstract class AsyncDiffRequestChain extends UserDataHolderBase implements DiffRequestSelectionChain {
21 private final EventDispatcher<Listener> myDispatcher = EventDispatcher.create(Listener.class);
23 private volatile ListSelection<? extends DiffRequestProducer> myRequests = null;
25 @Nullable private ProgressIndicator myIndicator;
26 private int myAssignments = 0;
28 public void addListener(@NotNull Listener listener, @NotNull Disposable disposable) {
29 myDispatcher.addListener(listener, disposable);
32 public void removeListener(@NotNull Listener listener) {
33 myDispatcher.removeListener(listener);
37 public @NotNull ListSelection<? extends DiffRequestProducer> getListSelection() {
38 ListSelection<? extends DiffRequestProducer> requests = myRequests;
39 if (requests == null) {
40 return ListSelection.createSingleton(new DiffRequestProducerWrapper(new LoadingDiffRequest()));
46 @RequiresBackgroundThread
47 public ListSelection<? extends DiffRequestProducer> loadRequestsInBackground() {
49 return loadRequestProducers();
51 catch (DiffRequestProducerException e) {
52 return ListSelection.createSingleton(new DiffRequestProducerWrapper(new ErrorDiffRequest(e)));
57 public void onAssigned(boolean isAssigned) {
59 if (myAssignments == 0 && myIndicator == null) {
60 myIndicator = startLoading();
66 if (myAssignments == 0 && myIndicator != null) {
71 assert myAssignments >= 0;
76 private ProgressIndicator startLoading() {
77 if (myRequests != null) return null;
79 return BackgroundTaskUtil.executeAndTryWait(indicator -> {
80 ListSelection<? extends DiffRequestProducer> producers = loadRequestsInBackground();
82 indicator.checkCanceled();
83 applyLoadedChanges(producers);
89 private void applyLoadedChanges(@NotNull ListSelection<? extends DiffRequestProducer> producers) {
90 if (myRequests != null) return;
92 myRequests = producers;
95 myDispatcher.getMulticaster().onRequestsLoaded();
99 @RequiresBackgroundThread
100 protected abstract ListSelection<? extends DiffRequestProducer> loadRequestProducers() throws DiffRequestProducerException;
102 public interface Listener extends EventListener {
104 void onRequestsLoaded();