2 * Copyright 2000-2016 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.vcs.changes;
18 import com.intellij.openapi.application.ApplicationManager;
19 import com.intellij.openapi.diagnostic.Logger;
20 import com.intellij.openapi.progress.BackgroundTaskQueue;
21 import com.intellij.openapi.progress.ProgressIndicator;
22 import com.intellij.openapi.project.Project;
23 import com.intellij.openapi.ui.MessageType;
24 import com.intellij.openapi.util.Comparing;
25 import com.intellij.openapi.vcs.VcsException;
26 import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
27 import com.intellij.util.continuation.ModalityIgnorantBackgroundableTask;
28 import org.jetbrains.annotations.CalledInAwt;
29 import org.jetbrains.annotations.CalledInBackground;
30 import org.jetbrains.annotations.NotNull;
31 import org.jetbrains.annotations.Nullable;
36 * For presentation, which is itself in GenericDetails (not necessarily) - shown from time to time, but cached, and
37 * which is a listener to some intensive changes (a group of invalidating changes should provoke a reload, but "outdated"
38 * (loaded but already not actual) results should be thrown away)
40 * @author Irina.Chernushina
43 public abstract class AbstractRefreshablePanel<T> implements RefreshablePanel<Change> {
44 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.AbstractRefreshablePanel");
46 @NotNull private final Project myProject;
47 @NotNull private final String myLoadingTitle;
48 private Ticket myCurrentlySelected;
49 private Ticket mySetId;
50 private final Ticket myTicket;
51 private final DetailsPanel myDetailsPanel;
52 private final BackgroundTaskQueue myQueue;
53 private volatile boolean myDisposed;
55 protected AbstractRefreshablePanel(@NotNull Project project, @NotNull String loadingTitle, @NotNull BackgroundTaskQueue queue) {
57 myLoadingTitle = loadingTitle;
59 myTicket = new Ticket();
60 myDetailsPanel = new DetailsPanel();
61 myDetailsPanel.loading();
62 myDetailsPanel.layout();
66 public boolean refreshDataSynch() {
72 public void dataChanged() {
73 ApplicationManager.getApplication().assertIsDispatchThread();
79 public void refresh() {
80 ApplicationManager.getApplication().assertIsDispatchThread();
82 if (!Comparing.equal(myCurrentlySelected, myTicket)) {
83 Ticket copy = myTicket.copy();
84 Ticket previousId = myCurrentlySelected;
85 myCurrentlySelected = copy;
87 if (!Comparing.equal(copy, previousId)) {
88 myQueue.run(new Loader(myProject, myLoadingTitle, copy));
91 myDetailsPanel.loading();
92 myDetailsPanel.layout();
94 refreshPresentation();
98 protected abstract void refreshPresentation();
101 protected abstract T loadImpl() throws VcsException;
103 protected abstract JPanel dataToPresentation(final T t);
104 protected abstract void disposeImpl();
107 private void acceptData(final T t) {
108 final JPanel panel = dataToPresentation(t);
109 myDetailsPanel.data(panel);
110 myDetailsPanel.layout();
114 public JPanel getPanel() {
115 return myDetailsPanel.getPanel();
119 public boolean isStillValid(Change data) {
123 private class Loader extends ModalityIgnorantBackgroundableTask {
124 private final Ticket myTicketCopy;
127 private Loader(@Nullable Project project, @NotNull String title, final Ticket ticketCopy) {
128 super(project, title, false);
129 myTicketCopy = ticketCopy;
133 protected void doInAwtIfFail(@NotNull Exception e) {
134 final Exception cause;
135 if (e instanceof RuntimeException && e.getCause() != null) {
136 cause = (Exception) e.getCause();
141 String message = cause.getMessage() == null ? e.getMessage() : cause.getMessage();
142 message = message == null ? "Unknown error" : message;
143 VcsBalloonProblemNotifier.showOverChangesView(myProject, message, MessageType.ERROR);
147 protected void doInAwtIfCancel() {
151 protected void doInAwtIfSuccess() {
152 if (myDisposed) return;
154 if (!myTicketCopy.equals(mySetId) && myTicketCopy.equals(myCurrentlySelected)) {
155 mySetId = myTicketCopy;
161 protected void runImpl(@NotNull ProgressIndicator indicator) {
162 if (myDisposed) return;
166 catch (VcsException e) {
167 throw new RuntimeException(e);
173 public void dispose() {
178 private static class Ticket {
185 public Ticket(int id) {
189 public Ticket copy() {
190 return new Ticket(myId);
193 public void increment() {
198 public boolean equals(Object o) {
199 if (this == o) return true;
200 if (o == null || getClass() != o.getClass()) return false;
202 Ticket ticket = (Ticket)o;
204 if (myId != ticket.myId) return false;
210 public int hashCode() {