Revert "drop OpenAnotherLogTabAction.InEditor"

This reverts commit baeeb72df99a9459f8242c83778f6cf0d613c443.

GitOrigin-RevId: 7079da2623ae885f0a4b26086d57cdcaa11f5740
This commit is contained in:
Gregory.Shrago
2024-10-29 17:35:27 +04:00
committed by intellij-monorepo-bot
parent bc6a8fda82
commit bfac111af4
7 changed files with 238 additions and 10 deletions

View File

@@ -93,6 +93,10 @@
<customizableActionGroupProvider implementation="com.intellij.vcs.log.ui.actions.VcsLogCustomizableActionGroupProvider"/>
<virtualFileSystem key="vcs-log" implementationClass="com.intellij.vcs.log.ui.editor.VcsLogVirtualFileSystem"/>
<fileIconProvider implementation="com.intellij.vcs.log.ui.editor.VcsLogIconProvider"/>
<fileEditorProvider id="VcsLogEditor" implementation="com.intellij.vcs.log.ui.editor.VcsLogEditorProvider" fileType="VcsLog"/>
<editorTabTitleProvider implementation="com.intellij.vcs.log.ui.editor.DefaultVcsLogFileTabTitleProvider"/>
<openTelemetryExporterProvider implementation="com.intellij.vcs.log.statistics.VcsLogTelemetryExporter"/>
<bookmarkProvider implementation="com.intellij.vcs.log.ui.VcsLogBookmarkProvider"/>
@@ -140,6 +144,8 @@
<group class="com.intellij.vcs.log.ui.actions.HighlightersActionGroup" id="Vcs.Log.HighlightersActionGroup"/>
<action class="com.intellij.vcs.log.ui.actions.OpenAnotherLogTabAction$InToolWindow" id="Vcs.Log.OpenAnotherTab"
icon="AllIcons.General.Add"/>
<action class="com.intellij.vcs.log.ui.actions.OpenAnotherLogTabAction$InEditor" id="Vcs.Log.OpenAnotherTabInEditor"
icon="AllIcons.Actions.OpenNewTab"/>
<action class="com.intellij.vcs.log.ui.actions.RefreshLogAction" id="Vcs.Log.Refresh" use-shortcut-of="Refresh" icon="AllIcons.Actions.Refresh"/>
<action class="com.intellij.vcs.log.ui.actions.ShowCommitTooltipAction" id="Vcs.Log.ShowTooltip"
use-shortcut-of="QuickJavaDoc"/>
@@ -198,6 +204,7 @@
<reference id="Vcs.Log.MatchCaseAction"/>
</group>
<group id="Vcs.Log.Toolbar.Internal">
<reference ref="Vcs.Log.OpenAnotherTabInEditor"/>
</group>
<group id="Vcs.Log.ContextMenu">
<reference id="Vcs.CopyRevisionNumberAction"/>
@@ -248,6 +255,7 @@
<reference id="Vcs.Log.OpenAnotherTab"/>
<group id="Vcs.Log.ToolWindow.TabActions.DropDown" icon="AllIcons.Toolbar.Expand" popup="true"
class="com.intellij.vcs.log.ui.actions.VcsLogToolWindowDropdownActionGroup">
<reference id="Vcs.Log.OpenAnotherTabInEditor"/>
<reference id="Vcs.ShowTabbedFileHistory"/>
<reference id="Vcs.ShowConsoleTab"/>
<separator/>
@@ -320,6 +328,7 @@
<separator/>
<reference ref="Vcs.Log.Refresh"/>
<reference ref="Vcs.Log.OpenAnotherTab"/>
<reference ref="Vcs.Log.OpenAnotherTabInEditor"/>
<reference ref="Vcs.Log.ResumeIndexing"/>
<reference id="Log.Unsorted.KeymapGroup"/>

View File

@@ -5,6 +5,7 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.VirtualFile
@@ -23,12 +24,22 @@ object VcsLogEditorUtil {
return FileEditorManager.getInstance(project).selectedEditors.flatMapTo(mutableSetOf(), ::getLogIds)
}
@JvmStatic
fun <T : VcsLogUiEx> findVcsLogUi(editors: Array<FileEditor>, clazz: Class<T>): T? {
return editors.asSequence().flatMap { VcsLogUiHolder.getLogUis(it.component) }.filterIsInstance(clazz).firstOrNull()
}
internal fun selectLogUi(project: Project, ui: VcsLogUi): Boolean {
val fileEditorManager = FileEditorManager.getInstance(project)
val editor = fileEditorManager.findLogFile(ui) ?: return false
return fileEditorManager.openFile(editor, true, true).isNotEmpty()
}
internal fun updateTabName(project: Project, ui: VcsLogUiEx) {
val fileEditorManager = FileEditorManagerEx.getInstanceEx(project)
fileEditorManager.findLogFile(ui)?.let { fileEditorManager.updateFilePresentation(it) }
}
private fun FileEditorManager.findLogFile(ui: VcsLogUi): VirtualFile? {
return allEditors.first { getLogIds(it).contains(ui.id) }?.file
}

View File

@@ -19,7 +19,6 @@ enum class VcsLogTabLocation {
TOOL_WINDOW {
override fun select(project: Project, logUi: VcsLogUi): Boolean = VcsLogContentUtil.selectLogUi(project, logUi)
},
@Deprecated("Unused")
EDITOR {
override fun select(project: Project, logUi: VcsLogUi): Boolean = VcsLogEditorUtil.selectLogUi(project, logUi)
},

View File

@@ -1,7 +1,11 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.vcs.log.impl
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.invokeLater
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.NlsContexts.TabTitle
@@ -19,9 +23,11 @@ import com.intellij.vcs.log.data.VcsLogData
import com.intellij.vcs.log.impl.VcsLogContentUtil.getToolWindow
import com.intellij.vcs.log.impl.VcsLogContentUtil.openLogTab
import com.intellij.vcs.log.impl.VcsLogContentUtil.updateLogUiName
import com.intellij.vcs.log.impl.VcsLogEditorUtil.findVcsLogUi
import com.intellij.vcs.log.impl.VcsLogManager.VcsLogUiFactory
import com.intellij.vcs.log.ui.MainVcsLogUi
import com.intellij.vcs.log.ui.VcsLogUiEx
import com.intellij.vcs.log.ui.editor.VcsLogVirtualFileSystem
import com.intellij.vcs.log.util.GraphOptionsUtil.presentationForTabTitle
import com.intellij.vcs.log.visible.filters.getPresentation
import org.jetbrains.annotations.ApiStatus
@@ -51,12 +57,19 @@ class VcsLogTabsManager internal constructor(private val project: Project,
LOG.warn("Reopening standalone tabs is not supported")
}
if (toolWindowTabs.isNotEmpty() || editorTabs.isNotEmpty()) {
if (editorTabs.isNotEmpty()) {
invokeLater(ModalityState.nonModal()) {
if (logManager.isDisposed) return@invokeLater
LOG.debug("Reopening editor tabs with ids: $editorTabs")
editorTabs.forEach { openEditorLogTab(it, false, null) }
}
}
if (toolWindowTabs.isNotEmpty()) {
futureToolWindow.thenAccept { toolWindow ->
if (!LOG.assertTrue(!logManager.isDisposed, "Attempting to open tabs on disposed VcsLogManager")) return@thenAccept
LOG.debug("Reopening toolwindow tabs with ids: $toolWindowTabs")
toolWindowTabs.forEach { openToolWindowLogTab(toolWindow, it, false, null) }
editorTabs.forEach { openToolWindowLogTab(toolWindow, it, false, null) }
}
}
@@ -86,7 +99,8 @@ class VcsLogTabsManager internal constructor(private val project: Project,
val tabId = generateTabId(logManager)
uiProperties.resetState(tabId)
if (location === VcsLogTabLocation.EDITOR) {
error("Unsupported")
val editors = openEditorLogTab(tabId, true, filters)
return findVcsLogUi(editors, MainVcsLogUi::class.java)!!
}
else if (location === VcsLogTabLocation.TOOL_WINDOW) {
val toolWindow = VcsLogContentUtil.getToolWindowOrThrow(project)
@@ -96,6 +110,11 @@ class VcsLogTabsManager internal constructor(private val project: Project,
throw UnsupportedOperationException("Only log in editor or tool window is supported")
}
private fun openEditorLogTab(tabId: String, focus: Boolean, filters: VcsLogFilterCollection?): Array<FileEditor> {
val file = VcsLogVirtualFileSystem.Holder.getInstance().createVcsLogFile(project, tabId, filters)
return FileEditorManager.getInstance(project).openFile(file, focus, true)
}
private fun openToolWindowLogTab(toolWindow: ToolWindow, tabId: String, focus: Boolean,
filters: VcsLogFilterCollection?): MainVcsLogUi {
val factory = getPersistentVcsLogUiFactory(tabId, VcsLogTabLocation.TOOL_WINDOW, filters)

View File

@@ -1,9 +1,7 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.vcs.log.ui.actions;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
@@ -108,11 +106,36 @@ public abstract class OpenAnotherLogTabAction extends DumbAwareAction {
VcsLogManager logManager = VcsProjectLog.getInstance(project).getLogManager();
if (logManager == null) return VcsLogFilterObject.collection();
Collection<? extends VcsLogUi> uis = ContainerUtil.filterIsInstance(
logManager.getVisibleLogUis(VcsLogTabLocation.TOOL_WINDOW),
MainVcsLogUi.class);
Collection<? extends VcsLogUi> uis = ContainerUtil.filterIsInstance(logManager.getVisibleLogUis(VcsLogTabLocation.TOOL_WINDOW),
MainVcsLogUi.class);
if (uis.isEmpty()) return VcsLogFilterObject.collection();
return ContainerUtil.getFirstItem(uis).getFilterUi().getFilters();
}
}
@ApiStatus.Internal
public static class InEditor extends OpenAnotherLogTabAction {
@Override
public void update(@NotNull AnActionEvent e) {
super.update(e);
if (e.getData(PlatformDataKeys.TOOL_WINDOW) != null && ActionPlaces.VCS_LOG_TOOLBAR_PLACE.equals(e.getPlace())) {
e.getPresentation().setEnabledAndVisible(false);
}
}
@Override
protected @NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String getDescription(@Nls @NotNull String vcsName) {
return VcsLogBundle.message("vcs.log.action.description.open.new.tab.with.log.in.editor", vcsName);
}
@Override
protected @NotNull @Nls(capitalization = Nls.Capitalization.Title) String getText(@Nls @NotNull String vcsName) {
return VcsLogBundle.message("vcs.log.action.open.new.tab.with.log.in.editor", vcsName);
}
@Override
protected @NotNull VcsLogTabLocation getLocation(@NotNull AnActionEvent e) {
return VcsLogTabLocation.EDITOR;
}
}
}

View File

@@ -0,0 +1,128 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.vcs.log.ui.editor
import com.intellij.ide.ui.UISettings
import com.intellij.openapi.components.*
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.fileEditor.FileEditorManagerKeys
import com.intellij.openapi.fileEditor.impl.EditorTabTitleProvider
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFilePathWrapper
import com.intellij.openapi.vfs.VirtualFileSystem
import com.intellij.ui.components.JBPanelWithEmptyText
import com.intellij.util.xmlb.annotations.Tag
import com.intellij.vcs.log.VcsLogBundle
import com.intellij.vcs.log.VcsLogFilterCollection
import com.intellij.vcs.log.impl.*
import com.intellij.vcs.log.impl.VcsLogTabsManager.Companion.onDisplayNameChange
import com.intellij.vcs.log.ui.VcsLogPanel
import com.intellij.vcs.log.util.VcsLogUtil
import java.awt.BorderLayout
import javax.swing.JComponent
internal class DefaultVcsLogFile(private val pathId: VcsLogVirtualFileSystem.VcsLogComplexPath,
private var filters: VcsLogFilterCollection? = null) :
VcsLogFile(VcsLogTabsManager.getFullName(pathId.logId)), VirtualFilePathWrapper { //NON-NLS not displayed
private val fileSystemInstance: VcsLogVirtualFileSystem = VcsLogVirtualFileSystem.Holder.getInstance()
internal val tabId get() = pathId.logId
internal var tabName: String
get() = service<VcsLogEditorTabNameCache>().getTabName(path) ?: name
set(value) = service<VcsLogEditorTabNameCache>().putTabName(path, value)
init {
putUserData(FileEditorManagerKeys.FORBID_TAB_SPLIT, true)
}
override fun createMainComponent(project: Project): JComponent {
val panel = JBPanelWithEmptyText(BorderLayout()).withEmptyText(VcsLogBundle.message("vcs.log.is.loading"))
VcsLogUtil.runWhenVcsAndLogIsReady(project) { logManager ->
val projectLog = VcsProjectLog.getInstance(project)
val tabsManager = projectLog.tabManager ?: return@runWhenVcsAndLogIsReady
try {
val factory = tabsManager.getPersistentVcsLogUiFactory(tabId, VcsLogTabLocation.EDITOR, filters)
val ui = logManager.createLogUi(factory, VcsLogTabLocation.EDITOR)
tabName = VcsLogTabsManager.generateDisplayName(ui)
ui.onDisplayNameChange {
tabName = VcsLogTabsManager.generateDisplayName(ui)
VcsLogEditorUtil.updateTabName(project, ui)
}
if (filters != null) filters = null
panel.add(VcsLogPanel(logManager, ui), BorderLayout.CENTER)
}
catch (e: CannotAddVcsLogWindowException) {
LOG.error(e)
panel.emptyText.text = VcsLogBundle.message("vcs.log.duplicated.tab.id.error")
}
}
return panel
}
override fun getFileSystem(): VirtualFileSystem = fileSystemInstance
override fun getPath(): String {
return fileSystemInstance.getPath(pathId)
}
override fun enforcePresentableName(): Boolean = true
override fun getPresentableName(): String = tabName
override fun getPresentablePath(): String = tabName
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as DefaultVcsLogFile
return tabId == other.tabId
}
override fun hashCode(): Int {
return tabId.hashCode()
}
companion object {
private val LOG = logger<DefaultVcsLogFile>()
}
}
internal class DefaultVcsLogFileTabTitleProvider : EditorTabTitleProvider, DumbAware {
override fun getEditorTabTooltipText(project: Project, file: VirtualFile): String? {
if (file !is DefaultVcsLogFile) return null
return getEditorTabTitle(project, file)
}
override fun getEditorTabTitle(project: Project, file: VirtualFile): String? {
if (file !is DefaultVcsLogFile) return null
return file.tabName
}
}
@Service(Service.Level.APP)
@State(name = "Vcs.Log.Editor.Tab.Names", storages = [Storage(StoragePathMacros.CACHE_FILE)])
private class VcsLogEditorTabNameCache : SimplePersistentStateComponent<VcsLogEditorTabNameCache.MyState>(MyState()) {
fun getTabName(path: String) = state.pathToTabName[path]
fun putTabName(path: String, tabName: String) {
state.pathToTabName.remove(path)
state.pathToTabName[path] = tabName // to put recently changed paths at the end of the linked map
val limit = UISettings.getInstance().recentFilesLimit
while (state.pathToTabName.size > limit) {
val (firstPath, _) = state.pathToTabName.asIterable().first()
state.pathToTabName.remove(firstPath)
}
state.intIncrementModificationCount()
}
class MyState : BaseState() {
@get:Tag("path-to-tab-name")
val pathToTabName by linkedMap<String, String>()
}
}

View File

@@ -0,0 +1,39 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.vcs.log.ui.editor
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.vcs.editor.ComplexPathVirtualFileSystem
import com.intellij.vcs.editor.GsonComplexPathSerializer
import com.intellij.vcs.log.VcsLogFilterCollection
internal class VcsLogVirtualFileSystem :
ComplexPathVirtualFileSystem<VcsLogVirtualFileSystem.VcsLogComplexPath>(GsonComplexPathSerializer(VcsLogComplexPath::class.java)) {
override fun findOrCreateFile(project: Project, path: VcsLogComplexPath): VirtualFile {
return createVcsLogFile(path, null)
}
fun createVcsLogFile(project: Project, tabId: String, filters: VcsLogFilterCollection?): VirtualFile {
return createVcsLogFile(VcsLogComplexPath(project.locationHash, project.locationHash, tabId), filters)
}
private fun createVcsLogFile(pathId: VcsLogComplexPath, filters: VcsLogFilterCollection?): DefaultVcsLogFile {
return DefaultVcsLogFile(pathId, filters)
}
override fun getProtocol(): String = Holder.PROTOCOL
object Holder {
internal const val PROTOCOL = "vcs-log"
@JvmStatic
fun getInstance() = service<VirtualFileManager>().getFileSystem(PROTOCOL) as VcsLogVirtualFileSystem
}
data class VcsLogComplexPath(override val sessionId: String,
override val projectHash: String,
val logId: String) : ComplexPath
}