diff --git a/platform/platform-impl/src/com/intellij/ui/content/impl/TabbedContentImpl.java b/platform/platform-impl/src/com/intellij/ui/content/impl/TabbedContentImpl.java index 76d411ae7caf..a0391cb832ce 100644 --- a/platform/platform-impl/src/com/intellij/ui/content/impl/TabbedContentImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/content/impl/TabbedContentImpl.java @@ -95,6 +95,16 @@ public class TabbedContentImpl extends ContentImpl implements TabbedContent { setComponent(tab.second); } + public boolean findAndSelectContent(@NotNull JComponent contentComponent) { + String tabName = findTabNameByComponent(contentComponent); + if (tabName != null) { + setDisplayName(tabName); + setComponent(contentComponent); + return true; + } + return false; + } + @Override public String getTabName() { String selected = findTabNameByComponent(getComponent()); diff --git a/platform/platform-impl/src/com/intellij/util/ContentUtilEx.java b/platform/platform-impl/src/com/intellij/util/ContentUtilEx.java index a95e092ac2b9..fa7d277d4795 100644 --- a/platform/platform-impl/src/com/intellij/util/ContentUtilEx.java +++ b/platform/platform-impl/src/com/intellij/util/ContentUtilEx.java @@ -18,6 +18,7 @@ package com.intellij.util; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.ui.content.Content; @@ -30,6 +31,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.ArrayList; +import java.util.List; /** * @author Konstantin Bulenkov @@ -87,6 +89,51 @@ public class ContentUtilEx extends ContentsUtil { } } + /** + * Searches through all {@link Content simple} and {@link TabbedContent tabbed} contents of the given ContentManager, + * and selects the one which holds the specified {@code contentComponent}. + * + * @return true if the necessary content was found (and thus selected) among content components of the given ContentManager. + */ + public static boolean selectContent(@NotNull ContentManager manager, @NotNull final JComponent contentComponent, boolean requestFocus) { + for (Content content : manager.getContents()) { + if (content instanceof TabbedContentImpl) { + boolean found = ((TabbedContentImpl)content).findAndSelectContent(contentComponent); + if (found) { + manager.setSelectedContent(content, requestFocus); + return true; + } + } + else if (Comparing.equal(content.getComponent(), contentComponent)) { + manager.setSelectedContent(content, requestFocus); + return true; + } + } + return false; + } + + /** + * Searches through all {@link Content simple} and {@link TabbedContent tabbed} contents of the given ContentManager, + * trying to find the first one which matches the given condition. + */ + @Nullable + public static JComponent findContentComponent(@NotNull ContentManager manager, @NotNull Condition condition) { + for (Content content : manager.getContents()) { + if (content instanceof TabbedContentImpl) { + List> tabs = ((TabbedContentImpl)content).getTabs(); + for (Pair tab : tabs) { + if (condition.value(tab.second)) { + return tab.second; + } + } + } + else if (condition.value(content.getComponent())) { + return content.getComponent(); + } + } + return null; + } + public static int getSelectedTab(@NotNull TabbedContent content) { final JComponent current = content.getComponent(); int index = 0; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java index 5632df4dcbd2..16a45868ac8e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java @@ -108,8 +108,8 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton { private final VcsHistoryProvider myProvider; private final AnnotationProvider myAnnotationProvider; private VcsHistorySession myHistorySession; - private final FilePath myFilePath; - private final FileHistoryRefresherI myRefresherI; + @NotNull private final FilePath myFilePath; + @NotNull private final FileHistoryRefresherI myRefresherI; private VcsFileRevision myBottomRevisionForShowDiff; private final DualView myDualView; @@ -346,9 +346,12 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton { } public FileHistoryPanelImpl(AbstractVcs vcs, - FilePath filePath, VcsHistorySession session, + @NotNull FilePath filePath, + VcsHistorySession session, VcsHistoryProvider provider, - ContentManager contentManager, final FileHistoryRefresherI refresherI, final boolean isStaticEmbedded) { + ContentManager contentManager, + @NotNull FileHistoryRefresherI refresherI, + final boolean isStaticEmbedded) { super(contentManager, provider.getHelpId() != null ? provider.getHelpId() : "reference.versionControl.toolwindow.history", ! isStaticEmbedded); myProject = vcs.getProject(); myIsStaticAndEmbedded = false; @@ -1500,6 +1503,16 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton { } } + @NotNull + public FileHistoryRefresherI getRefresher() { + return myRefresherI; + } + + @NotNull + public FilePath getFilePath() { + return myFilePath; + } + public VirtualFile getVirtualFile() { return myFilePath.getVirtualFile(); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryRefresher.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryRefresher.java index a3359163bd2f..63a5005bfed5 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryRefresher.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryRefresher.java @@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.history; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.annotate.AnnotationProvider; +import org.jetbrains.annotations.NotNull; /** * Refreshes file history. @@ -35,26 +36,34 @@ public class FileHistoryRefresher implements FileHistoryRefresherI { public FileHistoryRefresher(final VcsHistoryProvider vcsHistoryProvider, final AnnotationProvider annotationProvider, final FilePath path, - final String repositoryPath, final AbstractVcs vcs) { myVcsHistoryProvider = vcsHistoryProvider; myPath = path; myVcs = vcs; - mySessionPartner = new FileHistorySessionPartner(vcsHistoryProvider, annotationProvider, path, repositoryPath, vcs, this); + mySessionPartner = new FileHistorySessionPartner(vcsHistoryProvider, annotationProvider, path, vcs, this); myCanUseCache = true; } + @NotNull + public static FileHistoryRefresherI findOrCreate(@NotNull VcsHistoryProvider vcsHistoryProvider, + @NotNull AnnotationProvider annotationProvider, + @NotNull FilePath path, + @NotNull AbstractVcs vcs) { + FileHistoryRefresherI refresher = FileHistorySessionPartner.findExistingHistoryRefresher(vcs.getProject(), path); + return refresher == null ? new FileHistoryRefresher(vcsHistoryProvider, annotationProvider, path, vcs) : refresher; + } + /** * @param canUseLastRevision */ @Override public void run(boolean isRefresh, boolean canUseLastRevision) { + myIsRefresh = isRefresh; mySessionPartner.beforeRefresh(); final VcsHistoryProviderBackgroundableProxy proxy = new VcsHistoryProviderBackgroundableProxy( myVcs, myVcsHistoryProvider, myVcs.getDiffProvider()); proxy.executeAppendableSession(myVcs.getKeyInstanceMethod(), myPath, mySessionPartner, null, myCanUseCache, canUseLastRevision); myCanUseCache = false; - myIsRefresh = isRefresh; } /** diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistorySessionPartner.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistorySessionPartner.java index 2bda068d2c15..b3b7d6015c4b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistorySessionPartner.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistorySessionPartner.java @@ -16,7 +16,9 @@ package com.intellij.openapi.vcs.history; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsBundle; @@ -32,7 +34,9 @@ import com.intellij.util.BufferedListConsumer; import com.intellij.util.Consumer; import com.intellij.util.ContentUtilEx; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.util.List; /** @@ -44,7 +48,6 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar private final VcsHistoryProvider myVcsHistoryProvider; private final AnnotationProvider myAnnotationProvider; @NotNull private final FilePath myPath; - private final String myRepositoryPath; private final AbstractVcs myVcs; private final FileHistoryRefresherI myRefresherI; private volatile VcsAbstractHistorySession mySession; @@ -52,14 +55,12 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar public FileHistorySessionPartner(final VcsHistoryProvider vcsHistoryProvider, final AnnotationProvider annotationProvider, @NotNull final FilePath path, - final String repositoryPath, final AbstractVcs vcs, final FileHistoryRefresherI refresherI) { myVcsHistoryProvider = vcsHistoryProvider; myAnnotationProvider = annotationProvider; myPath = path; myLimitHistoryCheck = new LimitHistoryCheck(vcs.getProject(), path.getPath()); - myRepositoryPath = repositoryPath; myVcs = vcs; myRefresherI = refresherI; Consumer> sessionRefresher = new Consumer>() { @@ -86,6 +87,17 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar }; } + @Nullable + static FileHistoryRefresherI findExistingHistoryRefresher(@NotNull Project project, @NotNull final FilePath path) { + JComponent component = ContentUtilEx.findContentComponent(getToolWindow(project).getContentManager(), new Condition() { + @Override + public boolean value(JComponent component) { + return component instanceof FileHistoryPanelImpl && ((FileHistoryPanelImpl)component).getFilePath().equals(path); + } + }); + return component == null ? null : ((FileHistoryPanelImpl)component).getRefresher(); + } + public void acceptRevision(VcsFileRevision revision) { myLimitHistoryCheck.checkNumber(); myBuffer.consumeOne(revision); @@ -98,17 +110,6 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar return myFileHistoryPanel; } - private FileHistoryPanelImpl resetHistoryPanel() { - final VcsHistorySession copy = mySession.copyWithCachedRevision(); - if (myFileHistoryPanel == null) { - myFileHistoryPanel = createFileHistoryPanel(copy); - } - else { - myFileHistoryPanel.getHistoryPanelRefresh().consume(copy); - } - return myFileHistoryPanel; - } - @NotNull private FileHistoryPanelImpl createFileHistoryPanel(@NotNull VcsHistorySession copy) { ContentManager contentManager = ProjectLevelVcsManagerEx.getInstanceEx(myVcs.getProject()).getContentManager(); @@ -121,22 +122,29 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar if (mySession != null) { mySession.shouldBeRefreshed(); // to init current revision! } + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override public void run() { - myFileHistoryPanel = resetHistoryPanel(); - ToolWindow toolWindow = ToolWindowManager.getInstance(myVcs.getProject()).getToolWindow(ToolWindowId.VCS); - assert toolWindow != null : "Version Control ToolWindow should be available at this point."; - - ContentUtilEx.addTabbedContent(toolWindow.getContentManager(), myFileHistoryPanel, "History", myPath.getName(), - myRefresherI.isFirstTime()); - - if (myRefresherI.isFirstTime()) { - toolWindow.activate(null); + final VcsHistorySession copy = mySession.copyWithCachedRevision(); + if (myFileHistoryPanel == null) { + myFileHistoryPanel = createFileHistoryPanel(copy); + createOrSelectContentIfNeeded(); + } + else { + myFileHistoryPanel.getHistoryPanelRefresh().consume(copy); } } }); } + @NotNull + private static ToolWindow getToolWindow(@NotNull Project project) { + ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.VCS); + assert toolWindow != null : "Version Control ToolWindow should be available at this point."; + return toolWindow; + } + public void reportException(VcsException exception) { VcsBalloonProblemNotifier.showOverVersionControlView(myVcs.getProject(), VcsBundle.message("message.title.could.not.load.file.history") + ": " + @@ -146,6 +154,21 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar @Override public void beforeRefresh() { myLimitHistoryCheck.reset(); + if (myFileHistoryPanel != null) { + createOrSelectContentIfNeeded(); + } + } + + private void createOrSelectContentIfNeeded() { + ToolWindow toolWindow = getToolWindow(myVcs.getProject()); + if (myRefresherI.isFirstTime()) { + ContentManager manager = toolWindow.getContentManager(); + boolean selectedExistingContent = ContentUtilEx.selectContent(manager, myFileHistoryPanel, true); + if (!selectedExistingContent) { + ContentUtilEx.addTabbedContent(manager, myFileHistoryPanel, "History", myPath.getName(), true); + } + toolWindow.activate(null); + } } public void finished() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java index c616c0d4eaf4..79c5f76438dd 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java @@ -129,8 +129,8 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper { public void showFileHistory(final VcsHistoryProvider vcsHistoryProvider, final AnnotationProvider annotationProvider, final FilePath path, final String repositoryPath, final AbstractVcs vcs) { - final FileHistoryRefresherI refresherI = new FileHistoryRefresher(vcsHistoryProvider, annotationProvider, path, repositoryPath, vcs); - refresherI.run(false, true); + FileHistoryRefresherI refresher = FileHistoryRefresher.findOrCreate(vcsHistoryProvider, annotationProvider, path, vcs); + refresher.run(false, true); } public void showRollbackChangesDialog(List changes) {