[vcs-log] always create log on start if project has dvcs roots; schedule first refresh only if log tab is opened

This commit is contained in:
Julia Beliaeva
2016-05-05 19:03:21 +03:00
parent bb135a42d9
commit a6142f0225
4 changed files with 131 additions and 79 deletions
@@ -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;
}
@@ -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);
}
});
}
}
}
@@ -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<VcsRoot> roots) {
this(project, uiProperties, roots, null);
this(project, uiProperties, roots, true, null);
}
public VcsLogManager(@NotNull Project project,
@NotNull VcsLogTabsProperties uiProperties,
@NotNull Collection<VcsRoot> 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;
@@ -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<ProjectLogListener> 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<VcsLogManager> {
@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();
}
}