[collab/github/space] move wrapper method

GitOrigin-RevId: 9e5b453f3154f6e7f561b1ec90171aff5392a2d7
This commit is contained in:
Ivan Semenov
2023-01-18 15:17:10 +01:00
committed by intellij-monorepo-bot
parent b353c21f4f
commit b7a31de0a8
3 changed files with 148 additions and 157 deletions

View File

@@ -1,130 +0,0 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.collaboration.ui.codereview.timeline.comment
import com.intellij.collaboration.ui.CollaborationToolsUIUtil
import com.intellij.collaboration.ui.codereview.CodeReviewChatItemUIUtil
import com.intellij.collaboration.ui.icon.IconsProvider
import com.intellij.ui.scale.JBUIScale
import com.intellij.util.ui.JBInsets
import org.jetbrains.annotations.Nls
import java.awt.*
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.JPanel
import kotlin.math.max
import kotlin.math.min
object CommentInputComponentFactory {
fun <T> addIconLeft(componentType: CodeReviewChatItemUIUtil.ComponentType, item: JComponent,
iconProvider: IconsProvider<T>, iconKey: T, iconTooltip: @Nls String? = null): JComponent {
val iconLabel = JLabel(iconProvider.getIcon(iconKey, componentType.iconSize)).apply {
toolTipText = iconTooltip
}
return JPanel(CommentFieldWithIconLayout(componentType.iconGap - CollaborationToolsUIUtil.getFocusBorderInset())).apply {
isOpaque = false
add(CommentFieldWithIconLayout.ICON, iconLabel)
add(CommentFieldWithIconLayout.ITEM, item)
}
}
}
/**
* Lays out the field with an icon on the left.
* Icon is aligned to the top of its column except when min height of the field is less than that of an icon,
* in this case avatar is centered along that min height.
* Same thing the other way around.
*/
private class CommentFieldWithIconLayout(
private val gap: Int
) : LayoutManager {
companion object {
const val ICON = "ICON"
const val ITEM = "ITEM"
}
private var iconComponent: Component? = null
private var itemComponent: Component? = null
override fun addLayoutComponent(name: String, comp: Component?) {
when (name) {
ICON -> iconComponent = comp
ITEM -> itemComponent = comp
else -> error("Incorrect name $name")
}
}
override fun removeLayoutComponent(comp: Component) {
if (iconComponent == comp) iconComponent = null
if (itemComponent == comp) itemComponent = null
}
override fun preferredLayoutSize(parent: Container): Dimension = getSize(parent, Component::getPreferredSize)
override fun minimumLayoutSize(parent: Container): Dimension = getSize(parent, Component::getMinimumSize)
private fun getSize(parent: Container, sizeGetter: (Component) -> Dimension?): Dimension {
val iconSize = iconComponent?.takeIf { it.isVisible }?.let(sizeGetter) ?: Dimension(0, 0)
val itemSize = itemComponent?.takeIf { it.isVisible }?.let(sizeGetter) ?: Dimension(0, 0)
val gap = JBUIScale.scale(gap)
val i = parent.insets
return Dimension(i.left + iconSize.width + gap + itemSize.width + i.right,
i.top + max(iconSize.height, itemSize.height) + i.bottom)
}
override fun layoutContainer(parent: Container) {
val bounds = Rectangle(Point(0, 0), parent.size)
JBInsets.removeFrom(bounds, parent.insets)
var x = bounds.x
val y = bounds.y
var contentWidth = bounds.width
val contentHeight = bounds.height
val iconHeight = iconComponent?.takeIf { it.isVisible }?.preferredSize?.height ?: 0
val itemMinHeight = itemComponent?.takeIf { it.isVisible }?.minimumSize?.height ?: 0
iconComponent?.takeIf { it.isVisible }?.apply {
val prefSize = preferredSize
val width = min(contentWidth, prefSize.width)
setBounds(x, y + max(0, (itemMinHeight - iconHeight) / 2), width, min(contentHeight, prefSize.height))
x += prefSize.width
x += JBUIScale.scale(gap)
contentWidth -= width
contentWidth -= JBUIScale.scale(gap)
}
itemComponent?.takeIf { it.isVisible }?.apply {
val maxSize = maximumSize
val minSize = minimumSize
val width = if (contentWidth >= maxSize.width) {
maxSize.width
}
else {
if (contentWidth >= minSize.width) {
contentWidth
}
else {
minSize.width
}
}
val height = if (contentHeight >= maxSize.height) {
maxSize.height
}
else {
if (contentHeight >= minSize.height) {
contentHeight
}
else {
minSize.height
}
}
setBounds(x, y + max(0, (iconHeight - itemMinHeight) / 2), width, height)
}
}
}

View File

@@ -1,6 +1,9 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.collaboration.ui.codereview.timeline.comment
import com.intellij.collaboration.ui.CollaborationToolsUIUtil
import com.intellij.collaboration.ui.codereview.CodeReviewChatItemUIUtil
import com.intellij.collaboration.ui.icon.IconsProvider
import com.intellij.openapi.actionSystem.PlatformCoreDataKeys
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.actions.IncrementalFindAction
@@ -11,12 +14,18 @@ import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
import com.intellij.openapi.fileTypes.FileTypes
import com.intellij.openapi.project.Project
import com.intellij.ui.EditorTextField
import com.intellij.ui.scale.JBUIScale
import com.intellij.util.ui.JBInsets
import com.intellij.util.ui.UIUtil
import org.jetbrains.annotations.Nls
import java.awt.Rectangle
import java.awt.*
import java.awt.event.ComponentAdapter
import java.awt.event.ComponentEvent
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.JPanel
import kotlin.math.max
import kotlin.math.min
object CommentTextFieldFactory {
fun create(
@@ -79,34 +88,147 @@ object CommentTextFieldFactory {
class ScrollToComponent(val component: JComponent) : ScrollOnChangePolicy()
}
private class CommentTextField(
project: Project?,
document: Document
) : EditorTextField(document, project, FileTypes.PLAIN_TEXT) {
init {
isOneLineMode = false
fun <T> wrapWithLeftIcon(componentType: CodeReviewChatItemUIUtil.ComponentType, item: JComponent,
iconProvider: IconsProvider<T>, iconKey: T, iconTooltip: @Nls String? = null): JComponent {
val iconLabel = JLabel(iconProvider.getIcon(iconKey, componentType.iconSize)).apply {
toolTipText = iconTooltip
}
//always paint pretty border
override fun updateBorder(editor: EditorEx) = setupBorder(editor)
return JPanel(CommentFieldWithIconLayout(componentType.iconGap - CollaborationToolsUIUtil.getFocusBorderInset())).apply {
isOpaque = false
add(CommentFieldWithIconLayout.ICON, iconLabel)
add(CommentFieldWithIconLayout.ITEM, item)
}
}
}
override fun createEditor(): EditorEx {
// otherwise border background is painted from multiple places
return super.createEditor().apply {
//TODO: fix in editor
//com.intellij.openapi.editor.impl.EditorImpl.getComponent() == non-opaque JPanel
// which uses default panel color
component.isOpaque = false
//com.intellij.ide.ui.laf.darcula.ui.DarculaEditorTextFieldBorder.paintBorder
scrollPane.isOpaque = false
}
private class CommentTextField(
project: Project?,
document: Document
) : EditorTextField(document, project, FileTypes.PLAIN_TEXT) {
init {
isOneLineMode = false
}
//always paint pretty border
override fun updateBorder(editor: EditorEx) = setupBorder(editor)
override fun createEditor(): EditorEx {
// otherwise border background is painted from multiple places
return super.createEditor().apply {
//TODO: fix in editor
//com.intellij.openapi.editor.impl.EditorImpl.getComponent() == non-opaque JPanel
// which uses default panel color
component.isOpaque = false
//com.intellij.ide.ui.laf.darcula.ui.DarculaEditorTextFieldBorder.paintBorder
scrollPane.isOpaque = false
}
}
override fun getData(dataId: String): Any? {
if (PlatformCoreDataKeys.FILE_EDITOR.`is`(dataId)) {
return editor?.let { TextEditorProvider.getInstance().getTextEditor(it) } ?: super.getData(dataId)
}
return super.getData(dataId)
}
}
/**
* Lays out the field with an icon on the left.
* Icon is aligned to the top of its column except when min height of the field is less than that of an icon,
* in this case avatar is centered along that min height.
* Same thing the other way around.
*/
private class CommentFieldWithIconLayout(
private val gap: Int
) : LayoutManager {
companion object {
const val ICON = "ICON"
const val ITEM = "ITEM"
}
private var iconComponent: Component? = null
private var itemComponent: Component? = null
override fun addLayoutComponent(name: String, comp: Component?) {
when (name) {
ICON -> iconComponent = comp
ITEM -> itemComponent = comp
else -> error("Incorrect name $name")
}
}
override fun removeLayoutComponent(comp: Component) {
if (iconComponent == comp) iconComponent = null
if (itemComponent == comp) itemComponent = null
}
override fun preferredLayoutSize(parent: Container): Dimension = getSize(parent, Component::getPreferredSize)
override fun minimumLayoutSize(parent: Container): Dimension = getSize(parent, Component::getMinimumSize)
private fun getSize(parent: Container, sizeGetter: (Component) -> Dimension?): Dimension {
val iconSize = iconComponent?.takeIf { it.isVisible }?.let(sizeGetter) ?: Dimension(0, 0)
val itemSize = itemComponent?.takeIf { it.isVisible }?.let(sizeGetter) ?: Dimension(0, 0)
val gap = JBUIScale.scale(gap)
val i = parent.insets
return Dimension(i.left + iconSize.width + gap + itemSize.width + i.right,
i.top + max(iconSize.height, itemSize.height) + i.bottom)
}
override fun layoutContainer(parent: Container) {
val bounds = Rectangle(Point(0, 0), parent.size)
JBInsets.removeFrom(bounds, parent.insets)
var x = bounds.x
val y = bounds.y
var contentWidth = bounds.width
val contentHeight = bounds.height
val iconHeight = iconComponent?.takeIf { it.isVisible }?.preferredSize?.height ?: 0
val itemMinHeight = itemComponent?.takeIf { it.isVisible }?.minimumSize?.height ?: 0
iconComponent?.takeIf { it.isVisible }?.apply {
val prefSize = preferredSize
val width = min(contentWidth, prefSize.width)
setBounds(x, y + max(0, (itemMinHeight - iconHeight) / 2), width, min(contentHeight, prefSize.height))
x += prefSize.width
x += JBUIScale.scale(gap)
contentWidth -= width
contentWidth -= JBUIScale.scale(gap)
}
override fun getData(dataId: String): Any? {
if (PlatformCoreDataKeys.FILE_EDITOR.`is`(dataId)) {
return editor?.let { TextEditorProvider.getInstance().getTextEditor(it) } ?: super.getData(dataId)
itemComponent?.takeIf { it.isVisible }?.apply {
val maxSize = maximumSize
val minSize = minimumSize
val width = if (contentWidth >= maxSize.width) {
maxSize.width
}
return super.getData(dataId)
else {
if (contentWidth >= minSize.width) {
contentWidth
}
else {
minSize.width
}
}
val height = if (contentHeight >= maxSize.height) {
maxSize.height
}
else {
if (contentHeight >= minSize.height) {
contentHeight
}
else {
minSize.height
}
}
setBounds(x, y + max(0, (iconHeight - itemMinHeight) / 2), width, height)
}
}
}

View File

@@ -5,8 +5,8 @@ import com.intellij.collaboration.ui.CollaborationToolsUIUtil
import com.intellij.collaboration.ui.CollaborationToolsUIUtil.wrapWithProgressOverlay
import com.intellij.collaboration.ui.codereview.CodeReviewChatItemUIUtil
import com.intellij.collaboration.ui.codereview.comment.CommentInputActionsComponentFactory
import com.intellij.collaboration.ui.codereview.timeline.comment.CommentInputComponentFactory
import com.intellij.collaboration.ui.codereview.timeline.comment.CommentTextFieldFactory.create
import com.intellij.collaboration.ui.codereview.timeline.comment.CommentTextFieldFactory.wrapWithLeftIcon
import org.jetbrains.plugins.github.api.data.GHUser
import org.jetbrains.plugins.github.ui.avatars.GHAvatarIconsProvider
import javax.swing.JComponent
@@ -23,9 +23,8 @@ class GHCommentTextFieldFactory(private val model: GHCommentTextFieldModel) {
inputField
}
else {
CommentInputComponentFactory
.addIconLeft(avatar.componentType, inputField,
avatar.avatarIconsProvider, avatar.user.avatarUrl, avatar.user.getPresentableName())
wrapWithLeftIcon(avatar.componentType, inputField,
avatar.avatarIconsProvider, avatar.user.avatarUrl, avatar.user.getPresentableName())
}
return CommentInputActionsComponentFactory.attachActions(field, inputActions)