IJPL-796 refactor TabInfo (part 2)

GitOrigin-RevId: 08463bfc5a4e46a27bcec10d9b5ff9bfadf898e1
This commit is contained in:
Vladimir Krivosheev
2024-05-22 12:42:34 +02:00
committed by intellij-monorepo-bot
parent e4afc41f86
commit 067fb8916f
7 changed files with 123 additions and 117 deletions

View File

@@ -122,10 +122,10 @@ internal class TabbedMultiOutput(private val editor: Editor, parent: Disposable)
addTab(TabInfo(this).apply {
inlayOutput.preview?.let {
setIcon(it)
text = ""
setText("")
}
inlayOutput.title?.let {
text = inlayOutput.title
setText(it)
}
}).apply {
tabs.getTabLabel(this)?.apply {
@@ -142,7 +142,7 @@ internal class TabbedMultiOutput(private val editor: Editor, parent: Disposable)
private fun addTab(tabInfo: TabInfo, select: Boolean = false): TabInfo {
// We need to set empty DefaultActionGroup to move sideComponent to the right.
tabInfo.setActions(DefaultActionGroup(), ActionPlaces.UNKNOWN)
tabInfo.sideComponent = createTabToolbar(tabInfo)
tabInfo.setSideComponent(createTabToolbar(tabInfo))
tabs.addTab(tabInfo)
if (select) {
tabs.select(tabInfo, false)

View File

@@ -60,16 +60,16 @@ private fun TabInfo.appendUnreadIcon(tabLabel: TabLabel, unread: Int?) {
stopAlerting()
}
else {
alertIcon = AlertIcon(
setAlertIcon(AlertIcon(
CollaborationToolsIcons.Review.FileUnread,
0,
tabLabel.labelComponent.preferredSize.width + scale(3)
)
))
fireAlert()
resetAlertRequest()
}
}
private fun TabInfo.setUnreadTooltip(unread: Int?) {
tooltipText = if (unread != null && unread > 0) message("tooltip.code.review.files.not.viewed", unread) else null
setTooltipText(if (unread != null && unread > 0) message("tooltip.code.review.files.not.viewed", unread) else null)
}

View File

@@ -10740,6 +10740,7 @@ f:com.intellij.ui.tabs.TabInfo
- sf:ALERT_ICON:java.lang.String
- sf:ALERT_STATUS:java.lang.String
- sf:COMPONENT:java.lang.String
- sf:Companion:com.intellij.ui.tabs.TabInfo$Companion
- sf:ENABLED:java.lang.String
- sf:HIDDEN:java.lang.String
- sf:ICON:java.lang.String
@@ -10747,38 +10748,38 @@ f:com.intellij.ui.tabs.TabInfo
- sf:TAB_COLOR:java.lang.String
- sf:TEXT:java.lang.String
- <init>(javax.swing.JComponent):V
- append(java.lang.String,com.intellij.ui.SimpleTextAttributes):com.intellij.ui.tabs.TabInfo
- canBeDraggedOut():Z
- clearText(Z):com.intellij.ui.tabs.TabInfo
- fireAlert():V
- getActionsContextComponent():javax.swing.JComponent
- getAlertIcon():com.intellij.ui.content.AlertIcon
- getBlinkCount():I
- getChangeSupport():java.beans.PropertyChangeSupport
- getColoredText():com.intellij.ui.SimpleColoredText
- getComponent():javax.swing.JComponent
- getDefaultForeground():java.awt.Color
- getDragDelegate():com.intellij.ui.tabs.TabInfo$DragDelegate
- getDragOutDelegate():com.intellij.ui.tabs.TabInfo$DragOutDelegate
- getForeSideComponent():javax.swing.JComponent
- getGroup():com.intellij.openapi.actionSystem.ActionGroup
- getIcon():javax.swing.Icon
- getLastFocusOwner():javax.swing.JComponent
- getObject():java.lang.Object
- f:append(java.lang.String,com.intellij.ui.SimpleTextAttributes):com.intellij.ui.tabs.TabInfo
- f:canBeDraggedOut():Z
- f:clearText(Z):com.intellij.ui.tabs.TabInfo
- f:fireAlert():V
- f:getActionsContextComponent():javax.swing.JComponent
- f:getAlertIcon():com.intellij.ui.content.AlertIcon
- f:getBlinkCount():I
- f:getChangeSupport():java.beans.PropertyChangeSupport
- f:getColoredText():com.intellij.ui.SimpleColoredText
- f:getComponent():javax.swing.JComponent
- f:getDefaultForeground():java.awt.Color
- f:getDragDelegate():com.intellij.ui.tabs.TabInfo$DragDelegate
- f:getDragOutDelegate():com.intellij.ui.tabs.TabInfo$DragOutDelegate
- f:getForeSideComponent():javax.swing.JComponent
- f:getGroup():com.intellij.openapi.actionSystem.ActionGroup
- f:getIcon():javax.swing.Icon
- f:getLastFocusOwner():javax.swing.JComponent
- f:getObject():java.lang.Object
- getPlace():java.lang.String
- getPreferredFocusableComponent():javax.swing.JComponent
- getPreviousSelection():com.intellij.ui.tabs.TabInfo
- getSideComponent():javax.swing.JComponent
- getTabActionPlace():java.lang.String
- getTabColor():java.awt.Color
- getTabLabelActions():com.intellij.openapi.actionSystem.ActionGroup
- getTabPaneActions():com.intellij.openapi.actionSystem.ActionGroup
- getText():java.lang.String
- getTooltipText():java.lang.String
- isAlertRequested():Z
- isEnabled():Z
- isHidden():Z
- isPinned():Z
- f:getPreferredFocusableComponent():javax.swing.JComponent
- f:getPreviousSelection():com.intellij.ui.tabs.TabInfo
- f:getSideComponent():javax.swing.JComponent
- f:getTabActionPlace():java.lang.String
- f:getTabColor():java.awt.Color
- f:getTabLabelActions():com.intellij.openapi.actionSystem.ActionGroup
- f:getTabPaneActions():com.intellij.openapi.actionSystem.ActionGroup
- f:getText():java.lang.String
- f:getTooltipText():java.lang.String
- f:isAlertRequested():Z
- f:isEnabled():Z
- f:isHidden():Z
- f:isPinned():Z
- putInfo(java.util.Map):V
- resetAlertRequest():V
- revalidate():V

View File

@@ -5,9 +5,9 @@ import com.intellij.icons.AllIcons
import com.intellij.openapi.actionSystem.ActionGroup
import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.ui.Queryable
import com.intellij.openapi.util.Comparing
import com.intellij.openapi.util.NlsContexts
import com.intellij.ui.ClientProperty
import com.intellij.ui.LoadingNode.getText
import com.intellij.ui.PlaceProvider
import com.intellij.ui.SimpleColoredText
import com.intellij.ui.SimpleTextAttributes
@@ -25,7 +25,7 @@ import java.lang.ref.WeakReference
import javax.swing.Icon
import javax.swing.JComponent
class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
class TabInfo(var component: JComponent) : Queryable, PlaceProvider {
companion object {
const val ACTION_GROUP: String = "actionGroup"
const val ICON: String = "icon"
@@ -42,7 +42,7 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
private val DEFAULT_ALERT_ICON = AlertIcon(AllIcons.Nodes.TabAlert, 0, -JBUI.scale(6))
}
private var preferredFocusableComponent: JComponent?
private var preferredFocusableComponent: JComponent? = component
var group: ActionGroup? = null
private set
@@ -51,81 +51,99 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
var icon: Icon? = null
private set
private var place: @NonNls String? = null
var `object`: Any? = null
private set
var sideComponent: JComponent? = null
private set
var foreSideComponent: JComponent? = null
private set
private var lastFocusOwner: Reference<JComponent>? = null
private var lastFocusOwnerRef: Reference<JComponent>? = null
fun getLastFocusOwner() = lastFocusOwner?.get()
fun setLastFocusOwner(component: JComponent?) {
lastFocusOwner = component?.let { WeakReference(it) }
}
var lastFocusOwner: JComponent?
get() = lastFocusOwnerRef?.get()
set(value) {
lastFocusOwnerRef = value?.let { WeakReference(it) }
}
var tabLabelActions: ActionGroup? = null
private set
var tabPaneActions: ActionGroup? = null
private set
var tabActionPlace: String? = null
private set
private var alertIcon: AlertIcon? = null
var blinkCount: Int = 0
var isAlertRequested: Boolean = false
private set
var isHidden: Boolean = false
set(hidden) {
val old = field
field = hidden
changeSupport.firePropertyChange(HIDDEN, old, field)
}
var actionsContextComponent: JComponent? = null
private set
val coloredText: SimpleColoredText = SimpleColoredText()
var tooltipText: @NlsContexts.Tooltip String? = null
private set
private var defaultStyle = -1
var defaultForeground: Color? = null
private set
private var editorAttributes: TextAttributes? = null
private var defaultAttributes: SimpleTextAttributes? = null
var isEnabled: Boolean = true
set(enabled) {
val old = field
field = enabled
changeSupport.firePropertyChange(ENABLED, old, field)
}
var tabColor: Color? = null
private set
private var queryable: Queryable? = null
var dragOutDelegate: DragOutDelegate? = null
private set
var dragDelegate: DragDelegate? = null
/**
* The tab which was selected before the mouse was pressed on this tab. Focus will be transferred to that tab if this tab is dragged
* out of its container. (IDEA-61536)
*/
private var previousSelection = WeakReference<TabInfo?>(null)
private var previousSelectionRef: WeakReference<TabInfo>? = null
init {
preferredFocusableComponent = component
}
var previousSelection: TabInfo?
get() = previousSelectionRef?.get()
set(value) {
previousSelectionRef = value?.let { WeakReference(it) }
}
fun setText(text: @NlsContexts.TabTitle String): TabInfo {
val attributes = coloredText.attributes
val textAttributes = attributes.singleOrNull()?.toTextAttributes()
val defaultAttributes = getDefaultAttributes()
if (coloredText.toString() != text || !Comparing.equal(textAttributes, defaultAttributes.toTextAttributes())) {
if (coloredText.toString() != text || textAttributes != defaultAttributes.toTextAttributes()) {
clearText(false)
@Suppress("DialogTitleCapitalization")
append(text, defaultAttributes)
@@ -135,7 +153,7 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
private fun getDefaultAttributes(): SimpleTextAttributes {
if (defaultAttributes == null) {
val style = ((if (defaultStyle != -1) defaultStyle else SimpleTextAttributes.STYLE_PLAIN)
val style = ((if (defaultStyle == -1) SimpleTextAttributes.STYLE_PLAIN else defaultStyle)
or SimpleTextAttributes.STYLE_USE_EFFECT_COLOR)
if (editorAttributes != null) {
var attr = SimpleTextAttributes.fromTextAttributes(editorAttributes)
@@ -165,7 +183,7 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
return this
}
fun setIcon(icon: Icon): TabInfo {
fun setIcon(icon: Icon?): TabInfo {
val old = this.icon
if (old != icon) {
this.icon = icon
@@ -186,13 +204,10 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
val isPinned: Boolean
get() = ClientProperty.isTrue(component, JBTabsImpl.PINNED)
fun getText(): @NlsContexts.TabTitle String {
return coloredText.toString()
}
val text: @NlsContexts.TabTitle String
get() = coloredText.toString()
override fun getPlace(): String {
return place!!
}
override fun getPlace(): String? = place
fun setSideComponent(comp: JComponent?): TabInfo {
sideComponent = comp
@@ -222,9 +237,7 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
return this
}
fun getPreferredFocusableComponent(): JComponent {
return if (preferredFocusableComponent != null) preferredFocusableComponent!! else component!!
}
fun getPreferredFocusableComponent(): JComponent = preferredFocusableComponent ?: component
fun setPreferredFocusableComponent(component: JComponent?): TabInfo {
preferredFocusableComponent = component
@@ -264,13 +277,9 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
changeSupport.firePropertyChange(ALERT_STATUS, null, false)
}
override fun toString(): String {
return getText()
}
override fun toString(): String = getText()
fun getAlertIcon(): AlertIcon {
return if (alertIcon == null) DEFAULT_ALERT_ICON else alertIcon!!
}
fun getAlertIcon(): AlertIcon = alertIcon ?: DEFAULT_ALERT_ICON
fun resetAlertRequest() {
isAlertRequested = false
@@ -297,9 +306,8 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
return this
}
private fun update() {
setText(getText())
setText(text)
}
fun revalidate() {
@@ -318,7 +326,7 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
fun setTabColor(color: Color?): TabInfo {
val old = tabColor
if (!Comparing.equal(color, old)) {
if (color != old) {
tabColor = color
changeSupport.firePropertyChange(TAB_COLOR, old, color)
}
@@ -331,9 +339,7 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
}
override fun putInfo(info: MutableMap<in String, in String>) {
if (queryable != null) {
queryable!!.putInfo(info)
}
queryable?.putInfo(info)
}
fun setDragOutDelegate(delegate: DragOutDelegate?): TabInfo {
@@ -341,17 +347,8 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
return this
}
fun canBeDraggedOut(): Boolean {
return dragOutDelegate != null
}
fun canBeDraggedOut(): Boolean = dragOutDelegate != null
fun setPreviousSelection(previousSelection: TabInfo?) {
this.previousSelection = WeakReference(previousSelection)
}
fun getPreviousSelection(): TabInfo? {
return previousSelection.get()
}
interface DragDelegate {
fun dragStarted(mouseEvent: MouseEvent)
@@ -360,8 +357,11 @@ class TabInfo(var component: JComponent?) : Queryable, PlaceProvider {
interface DragOutDelegate {
fun dragOutStarted(mouseEvent: MouseEvent, info: TabInfo)
fun processDragOut(event: MouseEvent, source: TabInfo)
fun dragOutFinished(event: MouseEvent, source: TabInfo?)
fun dragOutCancelled(source: TabInfo?)
fun dragOutFinished(event: MouseEvent, source: TabInfo)
fun dragOutCancelled(source: TabInfo)
}
}

View File

@@ -121,13 +121,13 @@ open class JBTabsImpl(
if (component.isShowing) {
val width = component.width
val height = component.height
image = ImageUtil.createImage(info.component?.graphicsConfiguration, if (width > 0) width else 500, if (height > 0) height else 500,
image = ImageUtil.createImage(info.component.graphicsConfiguration, if (width > 0) width else 500, if (height > 0) height else 500,
BufferedImage.TYPE_INT_ARGB)
val g = image.createGraphics()
component.paint(g)
}
else {
image = ImageUtil.createImage(info.component?.graphicsConfiguration, 500, 500, BufferedImage.TYPE_INT_ARGB)
image = ImageUtil.createImage(info.component.graphicsConfiguration, 500, 500, BufferedImage.TYPE_INT_ARGB)
}
return image
}
@@ -1011,7 +1011,7 @@ open class JBTabsImpl(
val tabInfo = ClientProperty.get(renderer, TAB_INFO_KEY) ?: return
// The last one is expected to be 'CloseTab'
val tabAction = if (tabInfo.tabLabelActions != null) tabInfo.tabLabelActions.getChildren(null).lastOrNull() else null
val tabAction = if (tabInfo.tabLabelActions != null) tabInfo.tabLabelActions!!.getChildren(null).lastOrNull() else null
if (tabAction == null && !tabInfo.isPinned) {
return
}
@@ -1067,7 +1067,7 @@ open class JBTabsImpl(
// returns the icon that will be used in the hidden tabs list
protected open fun getTabActionIcon(info: TabInfo, isHovered: Boolean): Icon? {
val hasActions = info.tabLabelActions != null && info.tabLabelActions.getChildren(null).isNotEmpty()
val hasActions = info.tabLabelActions != null && info.tabLabelActions!!.getChildren(null).isNotEmpty()
val icon: Icon? = if (hasActions) {
if (isHovered) AllIcons.Actions.CloseHovered else AllIcons.Actions.Close
}
@@ -1161,9 +1161,9 @@ open class JBTabsImpl(
}
}
val toFocus: JComponent? = info.preferredFocusableComponent
val toFocus = info.getPreferredFocusableComponent()
LOG.debug { "preferred focusable component: $toFocus" }
if (toFocus == null || !toFocus.isShowing) {
if (!toFocus.isShowing) {
return null
}
@@ -2594,10 +2594,11 @@ open class JBTabsImpl(
if (field == value) {
return
}
field = value
for (tab in tabs) {
tab.sideComponent.isVisible = !field
tab.foreSideComponent.isVisible = !field
tab.sideComponent!!.isVisible = !field
tab.foreSideComponent!!.isVisible = !field
}
relayout(forced = true, layoutNow = true)
}
@@ -3424,8 +3425,12 @@ private class AccessibleTabPage(
}
}
private class TitleAction(private val tabs: JBTabsImpl,
private val titleProvider: () -> Pair<Icon, @Nls String>) : AnAction(), CustomComponentAction {
private val DUMMY_COMPONENT by lazy(LazyThreadSafetyMode.PUBLICATION) { JPanel() }
private class TitleAction(
private val tabs: JBTabsImpl,
private val titleProvider: () -> Pair<Icon, @Nls String>,
) : AnAction(), CustomComponentAction {
private val label = object : JLabel() {
override fun getPreferredSize(): Dimension {
val size = super.getPreferredSize()
@@ -3435,7 +3440,7 @@ private class TitleAction(private val tabs: JBTabsImpl,
override fun updateUI() {
super.updateUI()
font = TabLabel(tabs, TabInfo(null)).labelComponent.font
font = TabLabel(tabs, TabInfo(DUMMY_COMPONENT)).labelComponent.font
border = JBUI.Borders.empty(0, 5, 0, 6)
}
}

View File

@@ -57,13 +57,13 @@ public class TabLabel extends JPanel implements Accessible, EdtCompatibleDataPro
private final Wrapper labelPlaceholder = new Wrapper(false);
protected final JBTabsImpl tabs;
public TabLabel(JBTabsImpl tabs, final TabInfo info) {
public TabLabel(JBTabsImpl tabs, TabInfo info) {
super(false);
this.tabs = tabs;
this.info = info;
label = createLabel();
label = createLabel(tabs, info);
// Allow focus so that user can TAB into the selected TabLabel and then
// navigate through the other tabs using the LEFT/RIGHT keys.
@@ -198,14 +198,17 @@ public class TabLabel extends JPanel implements Accessible, EdtCompatibleDataPro
return tabs.getSelectedLabel() == this && super.isFocusable();
}
private SimpleColoredComponent createLabel() {
private @NotNull SimpleColoredComponent createLabel(@NotNull JBTabsImpl tabs, @Nullable TabInfo info) {
SimpleColoredComponent label = new SimpleColoredComponent() {
@Override
public Font getFont() {
Font font = super.getFont();
return (isFontSet() || !tabs.useSmallLabels()) ? font :
RelativeFont.NORMAL.fromResource("EditorTabs.fontSizeOffset", -2, JBUIScale.scale(11f)).derive(StartupUiUtil.getLabelFont());
if (isFontSet() || !tabs.useSmallLabels()) {
return font;
}
else {
return RelativeFont.NORMAL.fromResource("EditorTabs.fontSizeOffset", -2, JBUIScale.scale(11f)).derive(StartupUiUtil.getLabelFont());
}
}
@Override
@@ -241,7 +244,7 @@ public class TabLabel extends JPanel implements Accessible, EdtCompatibleDataPro
return baseForeground;
}
// Allows to edit the icon right before painting
// Allows editing the icon right before painting
public @NotNull Icon editIcon(@NotNull Icon baseIcon) {
return baseIcon;
}

View File

@@ -122,9 +122,9 @@ class EditorTabbedContainer internal constructor(
.setActiveTabFillIn(EditorColorsManager.getInstance().globalScheme.defaultBackground).setPaintFocus(false).jbTabs
.addListener(object : TabsListener {
override fun selectionChanged(oldSelection: TabInfo?, newSelection: TabInfo?) {
val oldEditor = if (oldSelection == null) null else window.manager.getSelectedEditor((oldSelection.getObject() as VirtualFile))
val oldEditor = if (oldSelection == null) null else window.manager.getSelectedEditor((oldSelection.`object` as VirtualFile))
oldEditor?.deselectNotify()
val newFile = (newSelection ?: return).getObject() as VirtualFile
val newFile = (newSelection ?: return).`object` as VirtualFile
val newEditor = newFile.let { window.manager.getSelectedEditor(newFile) }
newEditor?.selectNotify()
if (GeneralSettings.getInstance().isSyncOnFrameActivation) {
@@ -284,13 +284,13 @@ class EditorTabbedContainer internal constructor(
coroutineScope.launch {
val title = EditorTabPresentationUtil.getEditorTabTitle(project, file)
withContext(Dispatchers.EDT) {
tab.text = title
tab.setText(title)
}
}
coroutineScope.launch {
val color = readAction { EditorTabPresentationUtil.getEditorTabBackgroundColor(project, file) }
withContext(Dispatchers.EDT) {
tab.tabColor = color
tab.setTabColor(color)
}
}
@@ -322,7 +322,7 @@ class EditorTabbedContainer internal constructor(
override fun close() {
val selected = editorTabs.targetInfo ?: return
window.manager.closeFile((selected.getObject() as VirtualFile), window)
window.manager.closeFile((selected.`object` as VirtualFile), window)
}
private val isFloating: Boolean
@@ -344,11 +344,11 @@ class EditorTabbedContainer internal constructor(
if (tabInfo == info) {
continue
}
window.manager.closeFile((tabInfo.getObject() as VirtualFile), window)
window.manager.closeFile((tabInfo.`object` as VirtualFile), window)
}
}
else {
window.manager.closeFile((info.getObject() as VirtualFile), window)
window.manager.closeFile((info.`object` as VirtualFile), window)
}
}
@@ -370,7 +370,7 @@ class EditorTabbedContainer internal constructor(
override fun mouseClicked(e: MouseEvent) {
if (UIUtil.isActionClick(e, MouseEvent.MOUSE_CLICKED) && (e.isMetaDown || !SystemInfoRt.isMac && e.isControlDown)) {
val o = editorTabs.findInfo(e)?.getObject()
val o = editorTabs.findInfo(e)?.`object`
if (o is VirtualFile) {
ShowFilePathAction.show((o as VirtualFile?)!!, e)
}
@@ -443,7 +443,7 @@ class EditorTabbedContainer internal constructor(
editorTabs.select(previousSelection, true)
}
val file = info.getObject() as VirtualFile
val file = info.`object` as VirtualFile
this.file = file
file.putUserData(DRAG_START_INDEX_KEY, dragStartIndex)
file.putUserData(DRAG_START_LOCATION_HASH_KEY, System.identityHashCode(editorTabs))
@@ -456,12 +456,9 @@ class EditorTabbedContainer internal constructor(
val editors = window.getComposite(file)?.allEditors ?: emptyList()
val isNorthPanelAvailable = isNorthPanelAvailable(editors)
presentation.putClientProperty(DockManagerImpl.ALLOW_DOCK_TOOL_WINDOWS, !isSingletonEditorInWindow(editors))
session = dockManager.createDragSession(mouseEvent, createDockableEditor(img, file, presentation, window, isNorthPanelAvailable))
session = DockManager.getInstance(window.manager.project).createDragSession(mouseEvent, createDockableEditor(img, file, presentation, window, isNorthPanelAvailable))
}
private val dockManager: DockManager
get() = DockManager.getInstance(window.manager.project)
override fun processDragOut(event: MouseEvent, source: TabInfo) {
session!!.process(event)
}