diff --git a/plugins/github/resources/META-INF/plugin.xml b/plugins/github/resources/META-INF/plugin.xml
index ae7dc5ba1313..b75bfa68dc04 100644
--- a/plugins/github/resources/META-INF/plugin.xml
+++ b/plugins/github/resources/META-INF/plugin.xml
@@ -79,6 +79,9 @@
+
@@ -93,6 +96,9 @@
+
diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRToolWindowTabsContentManager.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRToolWindowTabsContentManager.kt
index bd393f94470f..2fe470127c1d 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRToolWindowTabsContentManager.kt
+++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRToolWindowTabsContentManager.kt
@@ -6,15 +6,19 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.Key
import com.intellij.ui.content.*
+import com.intellij.util.EventDispatcher
import com.intellij.util.IJSwingUtilities
import com.intellij.vcsUtil.VcsImplUtil
import org.jetbrains.annotations.CalledInAwt
import org.jetbrains.plugins.github.authentication.GithubAuthenticationManager
import org.jetbrains.plugins.github.util.GitRemoteUrlCoordinates
+import java.util.*
import javax.swing.JPanel
class GHPRToolWindowTabsContentManager(private val project: Project, private val contentManager: ContentManager) {
+ private val tabDisposalEventDispatcher = EventDispatcher.create(TabDisposalListener::class.java)
+
val currentTabs: Set
get() = contentManager.contents.mapNotNull { it.remoteUrl }.toSet()
@@ -38,8 +42,8 @@ class GHPRToolWindowTabsContentManager(private val project: Project, private val
}
@CalledInAwt
- internal fun addTab(remoteUrl: GitRemoteUrlCoordinates, onDispose: Disposable) {
- val content = createContent(remoteUrl, onDispose)
+ internal fun addTab(remoteUrl: GitRemoteUrlCoordinates) {
+ val content = createContent(remoteUrl)
contentManager.addContent(content)
updateTabNames()
}
@@ -56,10 +60,12 @@ class GHPRToolWindowTabsContentManager(private val project: Project, private val
contentManager.setSelectedContent(content, true)
}
- private fun createContent(remoteUrl: GitRemoteUrlCoordinates, onDispose: Disposable): Content {
+ private fun createContent(remoteUrl: GitRemoteUrlCoordinates): Content {
val disposable = Disposer.newDisposable()
- Disposer.register(disposable, Disposable { updateTabNames() })
- Disposer.register(disposable, onDispose)
+ Disposer.register(disposable, Disposable {
+ updateTabNames()
+ tabDisposalEventDispatcher.multicaster.tabDisposed(remoteUrl)
+ })
val content = ContentFactory.SERVICE.getInstance().createContent(JPanel(null), remoteUrl.remote.name, false)
content.isCloseable = true
@@ -86,12 +92,20 @@ class GHPRToolWindowTabsContentManager(private val project: Project, private val
}
}
+ fun addTabDisposalEventListener(listener: TabDisposalListener) = tabDisposalEventDispatcher.addListener(listener)
+
+ fun removeTabDisposalEventListener(listener: TabDisposalListener) = tabDisposalEventDispatcher.removeListener(listener)
+
private var Content.remoteUrl
get() = getUserData(REMOTE_URL)
set(value) {
putUserData(REMOTE_URL, value)
}
+ interface TabDisposalListener : EventListener {
+ fun tabDisposed(remoteUrl: GitRemoteUrlCoordinates)
+ }
+
companion object {
private val INIT_DONE_KEY = Key("GHPR_CONTENT_INIT_DONE")
private val REMOTE_URL = Key("GHPR_REMOTE_URL")
diff --git a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRToolWindowTabsManager.kt b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRToolWindowTabsManager.kt
index b7e44132277c..3d84ce652b43 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRToolWindowTabsManager.kt
+++ b/plugins/github/src/org/jetbrains/plugins/github/pullrequest/GHPRToolWindowTabsManager.kt
@@ -2,13 +2,16 @@
package org.jetbrains.plugins.github.pullrequest
import com.intellij.dvcs.repo.VcsRepositoryMappingListener
-import com.intellij.openapi.Disposable
+import com.intellij.ide.plugins.DynamicPluginListener
+import com.intellij.ide.plugins.IdeaPluginDescriptor
+import com.intellij.ide.plugins.PluginManager
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
+import com.intellij.openapi.project.ProjectManagerListener
import com.intellij.openapi.wm.ToolWindowManager
import git4idea.repo.GitRepository
import git4idea.repo.GitRepositoryChangeListener
@@ -27,10 +30,25 @@ internal class GHPRToolWindowTabsManager(private val project: Project) {
private val gitHelper = GithubGitHelper.getInstance()
private val settings = GithubPullRequestsProjectUISettings.getInstance(project)
- internal var contentManager: GHPRToolWindowTabsContentManager? by observable(null) { _, _, _ ->
- updateTabs()
+ private val tabDisposalListener = object : GHPRToolWindowTabsContentManager.TabDisposalListener {
+
+ var muted = false
+
+ override fun tabDisposed(remoteUrl: GitRemoteUrlCoordinates) {
+ if (!muted) {
+ if (gitHelper.getPossibleRemoteUrlCoordinates(project).contains(remoteUrl)) settings.addHiddenUrl(remoteUrl.url)
+ updateTabs()
+ }
+ }
}
+ internal var contentManager: GHPRToolWindowTabsContentManager?
+ by observable(null) { _, oldManager, newManager ->
+ oldManager?.removeTabDisposalEventListener(tabDisposalListener)
+ newManager?.addTabDisposalEventListener(tabDisposalListener)
+ updateTabs()
+ }
+
@CalledInAwt
fun isAvailable(): Boolean = getRemoteUrls().isNotEmpty()
@@ -56,11 +74,7 @@ internal class GHPRToolWindowTabsManager(private val project: Project) {
contentManager.removeTab(item)
}
for (item in delta.newItems) {
- contentManager.addTab(item, Disposable {
- //means that tab was closed by user
- if (gitHelper.getPossibleRemoteUrlCoordinates(project).contains(item)) settings.addHiddenUrl(item.url)
- ApplicationManager.getApplication().invokeLater({ updateTabs() }) { project.isDisposed }
- })
+ contentManager.addTab(item)
}
}
afterUpdate?.invoke()
@@ -91,6 +105,18 @@ internal class GHPRToolWindowTabsManager(private val project: Project) {
}
}
+ class BeforePluginUnloadListener(private val project: Project) : DynamicPluginListener {
+ override fun beforePluginUnload(pluginDescriptor: IdeaPluginDescriptor, isUpdate: Boolean) {
+ if (pluginDescriptor.pluginId == PluginManager.getInstance().getPluginOrPlatformByClassName(this::class.java.name)) {
+ muteTabDisposalListener(project)
+ }
+ }
+ }
+
+ class BeforeProjectCloseListener : ProjectManagerListener {
+ override fun projectClosing(project: Project) = muteTabDisposalListener(project)
+ }
+
companion object {
private inline fun runInEdt(project: Project, crossinline runnable: () -> Unit) {
val application = ApplicationManager.getApplication()
@@ -99,5 +125,9 @@ internal class GHPRToolWindowTabsManager(private val project: Project) {
}
private fun updateRemotes(project: Project) = project.service().updateTabs()
+
+ private fun muteTabDisposalListener(project: Project) {
+ project.service().tabDisposalListener.muted = true
+ }
}
}