diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/PostponableLogRefresher.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/PostponableLogRefresher.java index 8cdc70f5f7fa..d7df69e3431b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/PostponableLogRefresher.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/PostponableLogRefresher.java @@ -72,6 +72,10 @@ public class PostponableLogRefresher implements VcsLogRefresher { protected boolean canRefreshNow() { if (keepUpToDate()) return true; + return isLogVisible(); + } + + public boolean isLogVisible() { for (VcsLogWindow window : myLogWindows) { if (window.isVisible()) return true; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogContentProvider.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogContentProvider.java index 59c87d7a41b1..265688e0035e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogContentProvider.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogContentProvider.java @@ -15,11 +15,10 @@ */ package com.intellij.vcs.log.impl; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.VcsListener; +import com.intellij.openapi.vcs.changes.ui.ChangesViewContentEP; import com.intellij.openapi.vcs.changes.ui.ChangesViewContentProvider; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowId; @@ -27,7 +26,6 @@ import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.components.JBPanel; import com.intellij.ui.content.Content; import com.intellij.ui.content.TabbedContent; -import com.intellij.ui.content.impl.ContentManagerImpl; import com.intellij.util.ContentUtilEx; import com.intellij.util.ContentsUtil; import com.intellij.util.NotNullFunction; @@ -35,6 +33,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBusConnection; import com.intellij.vcs.log.ui.VcsLogPanel; import com.intellij.vcs.log.ui.VcsLogUiImpl; +import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -53,37 +52,49 @@ public class VcsLogContentProvider implements ChangesViewContentProvider { @NotNull private final Project myProject; @NotNull private final VcsLogProjectManager myLogManager; @NotNull private final JPanel myContainer = new JBPanel(new BorderLayout()); - private MessageBusConnection myConnection; public VcsLogContentProvider(@NotNull Project project, @NotNull VcsLogProjectManager logManager) { myProject = project; myLogManager = logManager; - myLogManager.setRecreateMainLogHandler(new Runnable() { + + MessageBusConnection connection = project.getMessageBus().connect(project); + connection.subscribe(VcsLogProjectManager.VCS_PROJECT_LOG_CHANGED, new VcsLogProjectManager.ProjectLogListener() { @Override - public void run() { - recreateLog(); + public void logCreated() { + addLogUi(); + } + + @Override + public void logDisposed() { + myContainer.removeAll(); + closeLogTabs(); } }); + + if (myLogManager.getLogManager() != null) { + addLogUi(); + } + } + + @CalledInAwt + private void addLogUi() { + myContainer.add(myLogManager.initMainLog(TAB_NAME), BorderLayout.CENTER); + + VcsLogManager manager = myLogManager.getLogManager(); + assert manager != null; + if (manager.isLogVisible()) myLogManager.scheduleInitialization(); } @Override public JComponent initContent() { - myConnection = myProject.getMessageBus().connect(); - myConnection.subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, new MyVcsListener()); - initContentInternal(); + myLogManager.scheduleInitialization(); return myContainer; } - private void initContentInternal() { - ApplicationManager.getApplication().assertIsDispatchThread(); - myContainer.add(myLogManager.initMainLog(TAB_NAME), BorderLayout.CENTER); - } - @Override public void disposeContent() { - myConnection.disconnect(); myContainer.removeAll(); - myLogManager.disposeLog(); + closeLogTabs(); } public static void openAnotherLogTab(@NotNull VcsLogManager logManager, @NotNull Project project) { @@ -97,6 +108,8 @@ public class VcsLogContentProvider implements ChangesViewContentProvider { ContentUtilEx .addTabbedContent(toolWindow.getContentManager(), new VcsLogPanel(logManager, logUi), TAB_NAME, shortName, true, logUi); toolWindow.activate(null); + + logManager.scheduleInitialization(); } @NotNull @@ -119,31 +132,12 @@ public class VcsLogContentProvider implements ChangesViewContentProvider { private void closeLogTabs() { ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.VCS); - for (Content content: toolWindow.getContentManager().getContents()) { - if (ContentUtilEx.isContentTab(content, TAB_NAME)) { - ContentsUtil.closeContentTab(toolWindow.getContentManager(), content); - } - } - } - - private void recreateLog() { - myContainer.removeAll(); - closeLogTabs(); - - myLogManager.disposeLog(); - - initContentInternal(); - } - - private class MyVcsListener implements VcsListener { - @Override - public void directoryMappingChanged() { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - recreateLog(); + if (toolWindow != null) { + for (Content content : toolWindow.getContentManager().getContents()) { + if (ContentUtilEx.isContentTab(content, TAB_NAME)) { + ContentsUtil.closeContentTab(toolWindow.getContentManager(), content); } - }); + } } } 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 69723bf5ba8e..37b04a5b7cc5 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 @@ -41,6 +41,7 @@ import com.intellij.vcs.log.graph.PermanentGraph; import com.intellij.vcs.log.ui.VcsLogColorManagerImpl; import com.intellij.vcs.log.ui.VcsLogPanel; import com.intellij.vcs.log.ui.VcsLogUiImpl; +import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -60,14 +61,16 @@ public class VcsLogManager implements Disposable { @NotNull private final VcsLogColorManagerImpl myColorManager; @NotNull private final VcsLogTabsWatcher myTabsLogRefresher; @NotNull private final PostponableLogRefresher myPostponableRefresher; + private boolean myInitialized = false; public VcsLogManager(@NotNull Project project, @NotNull VcsLogTabsProperties uiProperties, @NotNull Collection roots) { - this(project, uiProperties, roots, null); + this(project, uiProperties, roots, true, null); } public VcsLogManager(@NotNull Project project, @NotNull VcsLogTabsProperties uiProperties, @NotNull Collection roots, + boolean scheduleRefreshImmediately, @Nullable Runnable recreateHandler) { myProject = project; myUiProperties = uiProperties; @@ -82,11 +85,26 @@ public class VcsLogManager implements Disposable { myColorManager = new VcsLogColorManagerImpl(logProviders.keySet()); - myDataManager.refreshCompletely(); + if (scheduleRefreshImmediately) { + scheduleInitialization(); + } Disposer.register(project, this); } + @CalledInAwt + public void scheduleInitialization() { + if (!myInitialized) { + myInitialized = true; + myDataManager.refreshCompletely(); + } + } + + @CalledInAwt + public boolean isLogVisible() { + return myPostponableRefresher.isLogVisible(); + } + @NotNull public VcsLogDataManager getDataManager() { return myDataManager; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogProjectManager.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogProjectManager.java index bb088be9af23..56bcb550fa6f 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogProjectManager.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogProjectManager.java @@ -15,6 +15,7 @@ */ package com.intellij.vcs.log.impl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupActivity; @@ -23,11 +24,14 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsListener; import com.intellij.openapi.vcs.VcsRoot; +import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; +import com.intellij.util.messages.Topic; import com.intellij.vcs.log.data.VcsLogDataManager; import com.intellij.vcs.log.data.VcsLogTabsProperties; import com.intellij.vcs.log.ui.VcsLogPanel; import com.intellij.vcs.log.ui.VcsLogUiImpl; +import org.jetbrains.annotations.CalledInAny; import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +41,10 @@ import java.util.Arrays; import java.util.Collection; public class VcsLogProjectManager { + public static final Topic VCS_PROJECT_LOG_CHANGED = + Topic.create("Project Vcs Log Created or Disposed", ProjectLogListener.class); @NotNull private final Project myProject; + @NotNull private final MessageBus myMessageBus; @NotNull private final VcsLogTabsProperties myUiProperties; @NotNull @@ -46,6 +53,7 @@ public class VcsLogProjectManager { public VcsLogProjectManager(@NotNull Project project, @NotNull VcsLogTabsProperties uiProperties) { myProject = project; + myMessageBus = project.getMessageBus(); myUiProperties = uiProperties; } @@ -67,10 +75,6 @@ public class VcsLogProjectManager { return new VcsLogPanel(myLogManager.getValue(), myUi); } - public void setRecreateMainLogHandler(@Nullable Runnable recreateMainLogHandler) { - myLogManager.setRecreateMainLogHandler(recreateMainLogHandler); - } - /** * The instance of the {@link VcsLogUiImpl} or null if the log was not initialized yet. */ @@ -84,39 +88,48 @@ public class VcsLogProjectManager { return myLogManager.getCached(); } - public void disposeLog() { + @CalledInAny + private void recreateLog() { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + disposeLog(); + + if (hasDvcsRoots()) { + createLog(); + } + } + }); + } + + @CalledInAwt + private void disposeLog() { + if (myLogManager.getCached() != null) myMessageBus.syncPublisher(VCS_PROJECT_LOG_CHANGED).logDisposed(); myUi = null; myLogManager.drop(); } - void initOnStartup() { - Runnable command = new Runnable() { - @Override - public void run() { - if (hasDvcsRoots()) { - myLogManager.getValue(); - } - } - }; + @CalledInAwt + private void createLog() { + VcsLogManager logManager = myLogManager.getValue(); - MessageBusConnection connection = myProject.getMessageBus().connect(myProject); - connection.subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, new VcsListener() { - @Override - public void directoryMappingChanged() { - if (hasDvcsRoots()) { - new HeavyAwareExecutor(myProject).execute(command); - } - else { - disposeLog(); - } - } - }); + myMessageBus.syncPublisher(VCS_PROJECT_LOG_CHANGED).logCreated(); - if (hasDvcsRoots()) { - new HeavyAwareExecutor(myProject).execute(command); + if (PostponableLogRefresher.keepUpToDate()) { + new HeavyAwareExecutor(myProject).execute(new Runnable() { + @Override + public void run() { + logManager.scheduleInitialization(); + } + }); } } + public void scheduleInitialization() { + VcsLogManager cached = myLogManager.getCached(); + if (cached != null) cached.scheduleInitialization(); + } + private boolean hasDvcsRoots() { return !VcsLogManager.findLogProviders(getVcsRoots(), myProject).isEmpty(); } @@ -127,7 +140,6 @@ public class VcsLogProjectManager { @SuppressWarnings("NonPrivateFieldAccessedInSynchronizedContext") private class LazyVcsLogManager extends ClearableLazyValue { - @Nullable private Runnable myRecreateMainLogHandler; @NotNull @CalledInAwt @@ -140,7 +152,12 @@ public class VcsLogProjectManager { @CalledInAwt @Override protected synchronized VcsLogManager compute() { - return new VcsLogManager(myProject, myUiProperties, getVcsRoots(), myRecreateMainLogHandler); + return new VcsLogManager(myProject, myUiProperties, getVcsRoots(), false, new Runnable() { + @Override + public void run() { + recreateLog(); + } + }); } @CalledInAwt @@ -154,17 +171,36 @@ public class VcsLogProjectManager { public synchronized VcsLogManager getCached() { return myValue; } - - public synchronized void setRecreateMainLogHandler(@Nullable Runnable recreateMainLogHandler) { - myRecreateMainLogHandler = recreateMainLogHandler; - } } public static class InitLogStartupActivity implements StartupActivity { @Override public void runActivity(@NotNull Project project) { - if (!PostponableLogRefresher.keepUpToDate()) return; - getInstance(project).initOnStartup(); + VcsLogProjectManager logProjectManager = getInstance(project); + + MessageBusConnection connection = project.getMessageBus().connect(project); + connection.subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, new VcsListener() { + @Override + public void directoryMappingChanged() { + logProjectManager.recreateLog(); + } + }); + if (logProjectManager.hasDvcsRoots()) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + logProjectManager.createLog(); + } + }); + } } } + + public interface ProjectLogListener { + @CalledInAwt + void logCreated(); + + @CalledInAwt + void logDisposed(); + } }