From 73a800daa54d53c284fc7ff84764fa88e519ee3f Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 10 Oct 2014 18:14:22 +0400 Subject: [PATCH] [log] Send refresh events only to the proper instance of the log Instead of two event mechanism, introduce a single one: post evens when the VisiblePack is updated. Some clients need to know, whether the VisiblePack update was triggered by refresh or not, so supply a flag for them. --- .../vcs/log/VcsLogFilterChangeListener.java | 22 ------ .../com/intellij/vcs/log/VcsLogListener.java} | 16 +++- .../src/com/intellij/vcs/log/VcsLogUi.java | 4 +- .../log/data/ContainingBranchesGetter.java | 28 ++++--- .../vcs/log/data/VcsLogDataHolder.java | 6 +- .../intellij/vcs/log/impl/VcsLogManager.java | 1 + .../com/intellij/vcs/log/ui/VcsLogUiImpl.java | 21 ++--- .../vcs/log/ui/frame/BranchesPanel.java | 21 ++--- .../src/git4idea/branch/DeepComparator.java | 79 ++++++++----------- 9 files changed, 83 insertions(+), 115 deletions(-) delete mode 100644 platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterChangeListener.java rename platform/vcs-log/{impl/src/com/intellij/vcs/log/data/VcsLogRefreshListener.java => api/src/com/intellij/vcs/log/VcsLogListener.java} (53%) diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterChangeListener.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterChangeListener.java deleted file mode 100644 index 81f20021f573..000000000000 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterChangeListener.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2000-2014 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.vcs.log; - -public interface VcsLogFilterChangeListener { - - void filtersPossiblyChanged(); - -} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshListener.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogListener.java similarity index 53% rename from platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshListener.java rename to platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogListener.java index 4a9799264f4d..2d5dc5fbb5af 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshListener.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogListener.java @@ -13,15 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.vcs.log.data; +package com.intellij.vcs.log; import org.jetbrains.annotations.NotNull; /** - * This listener is notified about VCS log refresh procedure. + * Listens to changes in the log, both in Permanent and Visible parts. */ -public interface VcsLogRefreshListener { +public interface VcsLogListener { - void refresh(@NotNull DataPack dataPack); + /** + * This method is called whether a refresh happened, or filter changed, or the VisibleGraph was rebuilt. + *

+ * It is called on the EDT thread. + * + * @param dataPack new VcsLogDataPack which was just applied to the UI. + * @param refreshHappened true if a refresh initiated this log change, i.e. PermanentGraph changed. + */ + void onChange(@NotNull VcsLogDataPack dataPack, boolean refreshHappened); } diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java index 995407eaef52..b477e160d558 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java @@ -28,8 +28,8 @@ public interface VcsLogUi { void addHighlighter(@NotNull VcsLogHighlighter highlighter); void removeHighlighter(@NotNull VcsLogHighlighter highlighter); - void addFilterChangeListener(@NotNull VcsLogFilterChangeListener listener); - void removeFilterChangeListener(@NotNull VcsLogFilterChangeListener listener); + void addLogListener(@NotNull VcsLogListener listener); + void removeLogListener(@NotNull VcsLogListener listener); void setBranchesPanelVisible(boolean visible); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/ContainingBranchesGetter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/ContainingBranchesGetter.java index ff6a9ac156c1..d1576fd12390 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/ContainingBranchesGetter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/ContainingBranchesGetter.java @@ -18,12 +18,13 @@ package com.intellij.vcs.log.data; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ThrowableConsumer; import com.intellij.util.containers.SLRUMap; import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.VcsLogDataPack; +import com.intellij.vcs.log.VcsLogListener; import com.intellij.vcs.log.VcsRef; import com.intellij.vcs.log.util.SequentialLimitedLifoExecutor; import org.jetbrains.annotations.NotNull; @@ -38,7 +39,7 @@ import java.util.List; /** * Provides capabilities to asynchronously calculate "contained in branches" information. */ -public class ContainingBranchesGetter { +public class ContainingBranchesGetter implements VcsLogListener { private static final Logger LOG = Logger.getInstance(ContainingBranchesGetter.class); @@ -48,7 +49,7 @@ public class ContainingBranchesGetter { @Nullable private Runnable myLoadingFinishedListener; // access only from EDT private int myCurrentBranchesChecksum; - ContainingBranchesGetter(@NotNull Project project, @NotNull VcsLogDataHolder dataHolder, @NotNull Disposable parentDisposable) { + ContainingBranchesGetter(@NotNull VcsLogDataHolder dataHolder, @NotNull Disposable parentDisposable) { myDataHolder = dataHolder; myTaskExecutor = new SequentialLimitedLifoExecutor(parentDisposable, 10, new ThrowableConsumer() { @Override @@ -65,17 +66,18 @@ public class ContainingBranchesGetter { }); } }); - project.getMessageBus().connect(parentDisposable).subscribe(VcsLogDataHolder.REFRESH_COMPLETED, new VcsLogRefreshListener() { - @Override - public void refresh(@NotNull DataPack dataPack) { - Collection currentBranches = dataPack.getRefs().getBranches(); - int checksum = currentBranches.hashCode(); - if (myCurrentBranchesChecksum != 0 && myCurrentBranchesChecksum != checksum) { // clear cache if branches set changed after refresh - clearCache(); - } - myCurrentBranchesChecksum = checksum; + } + + @Override + public void onChange(@NotNull VcsLogDataPack dataPack, boolean refreshHappened) { + if (refreshHappened) { + Collection currentBranches = dataPack.getRefs().getBranches(); + int checksum = currentBranches.hashCode(); + if (myCurrentBranchesChecksum != 0 && myCurrentBranchesChecksum != checksum) { // clear cache if branches set changed after refresh + clearCache(); } - }); + myCurrentBranchesChecksum = checksum; + } } private void clearCache() { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java index 80d351204cba..8824594ccd53 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java @@ -28,7 +28,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; import com.intellij.util.ThrowableConsumer; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.messages.Topic; import com.intellij.vcs.log.*; import com.intellij.vcs.log.graph.PermanentGraph; import com.intellij.vcs.log.util.StopWatch; @@ -42,8 +41,6 @@ import java.util.Set; public class VcsLogDataHolder implements Disposable, VcsLogDataProvider { - public static final Topic REFRESH_COMPLETED = Topic.create("Vcs.Log.Completed", VcsLogRefreshListener.class); - private static final Logger LOG = Logger.getInstance(VcsLogDataHolder.class); @NotNull private final Project myProject; @@ -97,7 +94,7 @@ public class VcsLogDataHolder implements Disposable, VcsLogDataProvider { catch (IOException e) { throw new RuntimeException(e); // TODO: show a message to the user & fallback to using in-memory Hashes } - myContainingBranchesGetter = new ContainingBranchesGetter(project, this, this); + myContainingBranchesGetter = new ContainingBranchesGetter(this, this); myFilterer = new VcsLogFiltererImpl(myProject, myLogProviders, myHashMap, myTopCommitsDetailsCache, myDetailsGetter, uiProperties.isBek() ? PermanentGraph.SortType.Bek : PermanentGraph.SortType.Normal, @@ -107,7 +104,6 @@ public class VcsLogDataHolder implements Disposable, VcsLogDataProvider { @Override public void consume(DataPack dataPack) { myFilterer.onRefresh(dataPack); - myProject.getMessageBus().syncPublisher(REFRESH_COMPLETED).refresh(dataPack); } }; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java index 9cc4ac990efe..4e6b1b272006 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java @@ -79,6 +79,7 @@ public class VcsLogManager implements Disposable { final VcsLogDataHolder logDataHolder = new VcsLogDataHolder(myProject, this, logProviders, mySettings, myUiProperties, visiblePackConsumer); myUi = new VcsLogUiImpl(logDataHolder, myProject, mySettings, new VcsLogColorManagerImpl(logProviders.keySet()), myUiProperties, logDataHolder.getFilterer()); + myUi.addLogListener(logDataHolder.getContainingBranchesGetter()); // TODO: remove this after VcsLogDataHolder vs VcsLoUi dependency cycle is solved if (contentTabName != null) { myLogRefresher = new PostponeableLogRefresher(myProject, logDataHolder, contentTabName); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 45f0bc535af2..96f9be8bbb37 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -46,7 +46,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { @NotNull private final VcsLogUiProperties myUiProperties; @NotNull private final VcsLogFilterer myFilterer; - @NotNull private final Collection myFilterChangeListeners = ContainerUtil.newArrayList(); + @NotNull private final Collection myLogListeners = ContainerUtil.newArrayList(); @NotNull private VisiblePack myVisiblePack; @@ -69,13 +69,16 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { TIntHashSet previouslySelected = getSelectedCommits(); + PermanentGraph previousPermGraph = myVisiblePack.getPermanentGraph(); myVisiblePack = pack; + boolean permGraphChanged = previousPermGraph != myVisiblePack.getPermanentGraph(); + GraphTableModel newModel = new GraphTableModel(myVisiblePack, myLogDataHolder, this); setModel(newModel, myVisiblePack.getVisibleGraph(), previouslySelected); myMainFrame.updateDataPack(myVisiblePack); setLongEdgeVisibility(myUiProperties.areLongEdgesVisible()); - fireFilterChangeEvent(); + fireFilterChangeEvent(myVisiblePack, permGraphChanged); repaintUI(); } @@ -376,18 +379,18 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { } @Override - public void addFilterChangeListener(@NotNull VcsLogFilterChangeListener listener) { - myFilterChangeListeners.add(listener); + public void addLogListener(@NotNull VcsLogListener listener) { + myLogListeners.add(listener); } @Override - public void removeFilterChangeListener(@NotNull VcsLogFilterChangeListener listener) { - myFilterChangeListeners.remove(listener); + public void removeLogListener(@NotNull VcsLogListener listener) { + myLogListeners.remove(listener); } - private void fireFilterChangeEvent() { - for (VcsLogFilterChangeListener listener : myFilterChangeListeners) { - listener.filtersPossiblyChanged(); + private void fireFilterChangeEvent(@NotNull VisiblePack visiblePack, boolean refresh) { + for (VcsLogListener listener : myLogListeners) { + listener.onChange(visiblePack, refresh); } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java index cb78aec9333d..3ea5c106a45a 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java @@ -1,7 +1,6 @@ package com.intellij.vcs.log.ui.frame; import com.google.common.collect.Ordering; -import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.vfs.VirtualFile; @@ -12,14 +11,9 @@ import com.intellij.ui.components.JBScrollPane; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; -import com.intellij.vcs.log.RefGroup; -import com.intellij.vcs.log.VcsLogProvider; -import com.intellij.vcs.log.VcsLogRefManager; -import com.intellij.vcs.log.VcsRef; -import com.intellij.vcs.log.data.DataPack; +import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.RefsModel; import com.intellij.vcs.log.data.VcsLogDataHolder; -import com.intellij.vcs.log.data.VcsLogRefreshListener; import com.intellij.vcs.log.impl.SingletonRefGroup; import com.intellij.vcs.log.impl.VcsLogUtil; import com.intellij.vcs.log.ui.VcsLogUiImpl; @@ -84,11 +78,12 @@ public class BranchesPanel extends JPanel { } }); - Project project = dataHolder.getProject(); - project.getMessageBus().connect(project).subscribe(VcsLogDataHolder.REFRESH_COMPLETED, new VcsLogRefreshListener() { + myUI.addLogListener(new VcsLogListener() { @Override - public void refresh(@NotNull DataPack dataPack) { - rebuild(dataPack.getRefsModel()); + public void onChange(@NotNull VcsLogDataPack dataPack, boolean refresh) { + if (refresh) { + rebuild(dataPack.getRefs()); + } } }); } @@ -119,13 +114,13 @@ public class BranchesPanel extends JPanel { } } - public void rebuild(@NotNull RefsModel refsModel) { + public void rebuild(@NotNull VcsLogRefs refsModel) { myRefGroups = getRefsToDisplayOnPanel(refsModel); getParent().repaint(); } @NotNull - private List getRefsToDisplayOnPanel(@NotNull RefsModel refsModel) { + private List getRefsToDisplayOnPanel(@NotNull VcsLogRefs refsModel) { Collection allRefs = refsModel.getBranches(); List groups = ContainerUtil.newArrayList(); diff --git a/plugins/git4idea/src/git4idea/branch/DeepComparator.java b/plugins/git4idea/src/git4idea/branch/DeepComparator.java index b6df56e04347..d6d30dcc3c24 100644 --- a/plugins/git4idea/src/git4idea/branch/DeepComparator.java +++ b/plugins/git4idea/src/git4idea/branch/DeepComparator.java @@ -28,11 +28,7 @@ import com.intellij.openapi.vcs.VcsNotifier; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.JBColor; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.*; -import com.intellij.vcs.log.data.DataPack; -import com.intellij.vcs.log.data.VcsLogDataHolder; -import com.intellij.vcs.log.data.VcsLogRefreshListener; import com.intellij.vcs.log.impl.HashImpl; import git4idea.GitBranch; import git4idea.commands.GitCommand; @@ -54,7 +50,7 @@ public class DeepComparator implements Disposable { @NotNull private final Project myProject; @NotNull private final GitRepositoryManager myRepositoryManager; @NotNull private final VcsLogUi myUi; - @NotNull private final VcsLogFilterChangeListener myFilterChangeListener; + @NotNull private final VcsLogListener myLogListener; @Nullable private VcsLogHighlighter myHighlighter; @Nullable private MyTask myTask; @@ -71,64 +67,53 @@ public class DeepComparator implements Disposable { myUi = ui; Disposer.register(parent, this); - myFilterChangeListener = new VcsLogFilterChangeListener() { + myLogListener = new VcsLogListener() { @Override - public void filtersPossiblyChanged() { - if (myTask == null) { // no task in progress => not interested in filter changes - return; - } - - VcsLogBranchFilter branchFilter = myUi.getFilterUi().getFilters().getBranchFilter(); - if (branchFilter == null || - branchFilter.getBranchNames().size() != 1 || - !branchFilter.getBranchNames().iterator().next().equals(myTask.myComparedBranch)) { - stopAndUnhighlight(); - } - } - }; - myUi.addFilterChangeListener(myFilterChangeListener); - - project.getMessageBus().connect(project).subscribe(VcsLogDataHolder.REFRESH_COMPLETED, new VcsLogRefreshListener() { - @Override - public void refresh(@NotNull DataPack dataPack) { + public void onChange(@NotNull VcsLogDataPack dataPack, boolean refreshHappened) { if (myTask == null) { // no task in progress => not interested in refresh events return; } - // collect data - String comparedBranch = myTask.myComparedBranch; - Map repositoriesWithCurrentBranches = myTask.myRepositoriesWithCurrentBranches; - VcsLogDataProvider provider = myTask.myProvider; + if (refreshHappened) { + // collect data + String comparedBranch = myTask.myComparedBranch; + Map repositoriesWithCurrentBranches = myTask.myRepositoriesWithCurrentBranches; + VcsLogDataProvider provider = myTask.myProvider; - stopAndUnhighlight(); + stopAndUnhighlight(); - // highlight again - Map repositories = getRepositories(dataPack.getLogProviders(), comparedBranch); - if (repositories.equals(repositoriesWithCurrentBranches)) { // but not if current branch changed - highlightInBackground(comparedBranch, provider); + // highlight again + Map repositories = getRepositories(myUi.getDataPack().getLogProviders(), comparedBranch); + if (repositories.equals(repositoriesWithCurrentBranches)) { // but not if current branch changed + highlightInBackground(comparedBranch, provider); + } + } + else { + VcsLogBranchFilter branchFilter = myUi.getFilterUi().getFilters().getBranchFilter(); + if (branchFilter == null || + branchFilter.getBranchNames().size() != 1 || + !branchFilter.getBranchNames().iterator().next().equals(myTask.myComparedBranch)) { + stopAndUnhighlight(); + } } } - }); + }; + myUi.addLogListener(myLogListener); } - public void highlightInBackground(@NotNull final String branchToCompare, @NotNull final VcsLogDataProvider dataProvider) { + public void highlightInBackground(@NotNull String branchToCompare, @NotNull VcsLogDataProvider dataProvider) { if (myTask != null) { LOG.error("Shouldn't be possible"); return; } - UIUtil.invokeAndWaitIfNeeded(new Runnable() { - @Override - public void run() { - Map repositories = getRepositories(myUi.getDataPack().getLogProviders(), branchToCompare); - if (repositories.isEmpty()) { - return; - } + Map repositories = getRepositories(myUi.getDataPack().getLogProviders(), branchToCompare); + if (repositories.isEmpty()) { + return; + } - myTask = new MyTask(myProject, myUi, repositories, dataProvider, branchToCompare); - myTask.queue(); - } - }); + myTask = new MyTask(myProject, myUi, repositories, dataProvider, branchToCompare); + myTask.queue(); } @NotNull @@ -159,7 +144,7 @@ public class DeepComparator implements Disposable { @Override public void dispose() { stopAndUnhighlight(); - myUi.removeFilterChangeListener(myFilterChangeListener); + myUi.removeLogListener(myLogListener); } public boolean hasHighlightingOrInProgress() {