Skip to content

Commit

Permalink
Iterate on TextField and TextArea focused state UI (#540)
Browse files Browse the repository at this point in the history
* add example text to Swing TextArea in SwingComparisonTabPanel

Signed-off-by: Ivan Morgillo <[email protected]>

* fix TextArea cursor start padding

Signed-off-by: Ivan Morgillo <[email protected]>

* iterate on InputField focused UI

Signed-off-by: Ivan Morgillo <[email protected]>

* iterate on TextField and TextArea style and metrics

Signed-off-by: Ivan Morgillo <[email protected]>

* reformat IntUiBridge.kt

Signed-off-by: Ivan Morgillo <[email protected]>

* update API files

Signed-off-by: Ivan Morgillo <[email protected]>

* use retrieveArcAsCornerSize instead of manually pulling the constant

Signed-off-by: Ivan Morgillo <[email protected]>

* add more textfields to SwingComparisonTabPanel for further comparison

Signed-off-by: Ivan Morgillo <[email protected]>

* reformat

Signed-off-by: Ivan Morgillo <[email protected]>

* remove detekt-compose dependency from .idea/detect.xml

reference: #540 (comment)
Signed-off-by: Ivan Morgillo <[email protected]>

* remove redundant parameter in IntUiBridge TextFieldMetrics

reference: #540 (comment)
Signed-off-by: Ivan Morgillo <[email protected]>

* remove unnecessary focusOutlineExpand property

Signed-off-by: Ivan Morgillo <[email protected]>

* clean up Swing/Compose TextField comparison

Signed-off-by: Ivan Morgillo <[email protected]>

* re-enable logging in ResourcePainterProvider

Signed-off-by: Ivan Morgillo <[email protected]>

* tune TextArea paddings

Signed-off-by: Ivan Morgillo <[email protected]>

* update API files

Signed-off-by: Ivan Morgillo <[email protected]>

* restore previous minSize for TextField

Signed-off-by: Ivan Morgillo <[email protected]>

* reapply border fixed after scrollbar rebase

Signed-off-by: Ivan Morgillo <[email protected]>

* reformat InputField

Signed-off-by: Ivan Morgillo <[email protected]>

* tune TextFieldMetrics

Signed-off-by: Ivan Morgillo <[email protected]>

* Tweak paddings to better align with Swing

* TextField horizontal padding should consider the border, too
* TextArea padding should not apply to the scrollbar itself
* Tweak scrollbar min height to match Swing

---------

Signed-off-by: Ivan Morgillo <[email protected]>
  • Loading branch information
hamen authored Aug 26, 2024
1 parent d1c0567 commit 0816d43
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ private fun readDefaultDropdownStyle(menuStyle: MenuStyle): DropdownStyle {
DropdownMetrics(
arrowMinSize = DpSize(arrowWidth, minimumSize.height),
minSize = DpSize(minimumSize.width + arrowWidth, minimumSize.height),
cornerSize = CornerSize(DarculaUIUtil.COMPONENT_ARC.dp / 2),
cornerSize = componentArc,
contentPadding = retrieveInsetsAsPaddingValues("ComboBox.padding"),
borderWidth = DarculaUIUtil.LW.dp,
),
Expand Down Expand Up @@ -922,7 +922,7 @@ private fun readTextAreaStyle(metrics: TextFieldMetrics): TextAreaStyle {
metrics =
TextAreaMetrics(
cornerSize = metrics.cornerSize,
contentPadding = metrics.contentPadding,
contentPadding = PaddingValues(horizontal = 5.dp, vertical = 4.dp),
minSize = metrics.minSize,
borderWidth = metrics.borderWidth,
),
Expand Down Expand Up @@ -966,8 +966,8 @@ private fun readTextFieldStyle(): TextFieldStyle {
colors = colors,
metrics =
TextFieldMetrics(
cornerSize = CornerSize(DarculaUIUtil.COMPONENT_ARC.dp / 2),
contentPadding = PaddingValues(horizontal = 9.dp, vertical = 2.dp),
cornerSize = componentArc,
contentPadding = PaddingValues(horizontal = 8.dp + DarculaUIUtil.LW.dp),
minSize = DpSize(144.dp, minimumSize.height),
borderWidth = DarculaUIUtil.LW.dp,
),
Expand Down Expand Up @@ -1182,3 +1182,6 @@ private fun readIconButtonStyle(): IconButtonStyle =
borderHovered = retrieveColorOrUnspecified("ActionButton.hoverBorderColor"),
),
)

private val componentArc: CornerSize
get() = CornerSize(DarculaUIUtil.COMPONENT_ARC.dp / 2)
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,9 @@ private fun readScrollbarWindowsAndLinuxColors(isDark: Boolean): ScrollbarColors

private fun readScrollbarMetrics(): ScrollbarMetrics =
if (hostOs.isMacOS) {
ScrollbarMetrics(thumbCornerSize = CornerSize(percent = 100), minThumbLength = 20.dp)
ScrollbarMetrics(thumbCornerSize = CornerSize(percent = 100), minThumbLength = 24.dp)
} else {
ScrollbarMetrics(thumbCornerSize = CornerSize(0), minThumbLength = 16.dp)
ScrollbarMetrics(thumbCornerSize = CornerSize(0), minThumbLength = 24.dp)
}

private fun readTrackClickBehavior() =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,12 @@ public fun ScrollbarColors.Companion.windowsAndLinuxDark(

public fun ScrollbarMetrics.Companion.macOs(
thumbCornerSize: CornerSize = CornerSize(100),
minThumbLength: Dp = 20.dp,
minThumbLength: Dp = 24.dp,
): ScrollbarMetrics = ScrollbarMetrics(thumbCornerSize, minThumbLength)

public fun ScrollbarMetrics.Companion.windowsAndLinux(
thumbCornerSize: CornerSize = CornerSize(0),
minThumbLength: Dp = 20.dp,
minThumbLength: Dp = 24.dp,
): ScrollbarMetrics = ScrollbarMetrics(thumbCornerSize, minThumbLength)

public fun AlwaysVisible.Companion.default(): AlwaysVisible =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public fun TextAreaColors.Companion.dark(

public fun TextAreaMetrics.Companion.defaults(
cornerSize: CornerSize = CornerSize(4.dp),
contentPadding: PaddingValues = PaddingValues(horizontal = 6.dp, vertical = 2.dp),
contentPadding: PaddingValues = PaddingValues(horizontal = 5.dp, vertical = 4.dp),
minSize: DpSize = DpSize(144.dp, 28.dp),
borderWidth: Dp = 1.dp,
): TextAreaMetrics = TextAreaMetrics(borderWidth, contentPadding, cornerSize, minSize)
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public fun TextFieldColors.Companion.dark(

public fun TextFieldMetrics.Companion.defaults(
cornerSize: CornerSize = CornerSize(4.dp),
contentPadding: PaddingValues = PaddingValues(horizontal = 9.dp, vertical = 6.dp),
contentPadding: PaddingValues = PaddingValues(horizontal = 9.dp), // 8 + 1 (border)
minSize: DpSize = DpSize(144.dp, 28.dp),
borderWidth: Dp = 1.dp,
): TextFieldMetrics = TextFieldMetrics(borderWidth, contentPadding, cornerSize, minSize)
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ internal fun InputField(
val borderModifier =
Modifier.thenIf(!undecorated && borderColor.isSpecified && hasNoOutline) {
border(
alignment = Stroke.Alignment.Center,
alignment = Stroke.Alignment.Inside,
width = style.metrics.borderWidth,
color = borderColor,
shape = shape,
Expand All @@ -104,8 +104,14 @@ internal fun InputField(
modifier =
modifier
.then(backgroundModifier)
.thenIf(!undecorated && hasNoOutline) {
focusOutline(
state = inputFieldState,
outlineShape = shape,
alignment = Stroke.Alignment.Center,
)
}
.then(borderModifier)
.thenIf(!undecorated && hasNoOutline) { focusOutline(inputFieldState, shape) }
.outline(inputFieldState, outline, shape, Stroke.Alignment.Center),
enabled = enabled,
readOnly = readOnly,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.rememberScrollState
Expand Down Expand Up @@ -83,7 +84,7 @@ internal fun TextAreaScrollableContainer(
VerticalScrollbar(
scrollState,
style = style,
modifier = Modifier.pointerHoverIcon(PointerIcon.Default),
modifier = Modifier.pointerHoverIcon(PointerIcon.Default).padding(1.dp),
keepVisible = keepVisible,
)
},
Expand Down
33 changes: 9 additions & 24 deletions ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TextArea.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.offset
import org.jetbrains.annotations.ApiStatus.ScheduledForRemoval
import org.jetbrains.jewel.foundation.theme.JewelTheme
import org.jetbrains.jewel.foundation.theme.LocalContentColor
Expand Down Expand Up @@ -119,7 +118,7 @@ private fun NoTextAreaDecorator(style: TextAreaStyle, scrollbarStyle: ScrollbarS
TextAreaScrollableContainer(
scrollState = scrollState,
style = scrollbarStyle,
contentModifier = Modifier.padding(end = innerEndPadding),
contentModifier = Modifier.padding(style.metrics.borderWidth).padding(end = innerEndPadding),
content = { Box(Modifier.padding(contentPadding)) { innerTextField() } },
)
} else {
Expand Down Expand Up @@ -147,14 +146,13 @@ private fun TextAreaDecorator(
TextAreaScrollableContainer(
scrollState = scrollState,
style = scrollbarStyle,
contentModifier = Modifier.padding(end = innerEndPadding),
content = innerTextField,
contentModifier = Modifier.padding(style.metrics.borderWidth).padding(end = innerEndPadding),
content = { Box(Modifier.padding(contentPadding)) { innerTextField() } },
)
} else {
innerTextField()
Box(Modifier.padding(contentPadding)) { innerTextField() }
}
},
contentPadding = contentPadding,
placeholderTextColor = style.colors.placeholder,
placeholder = if (state.text.isEmpty()) placeholder else null,
textStyle = textStyle,
Expand Down Expand Up @@ -291,7 +289,6 @@ public fun TextArea(
) { innerTextField, _ ->
TextAreaDecorationBox(
innerTextField = innerTextField,
contentPadding = style.metrics.contentPadding,
placeholderTextColor = style.colors.placeholder,
placeholder = if (value.text.isEmpty()) placeholder else null,
textStyle = textStyle,
Expand All @@ -303,7 +300,6 @@ public fun TextArea(
@Composable
private fun TextAreaDecorationBox(
innerTextField: @Composable () -> Unit,
contentPadding: PaddingValues,
textStyle: TextStyle,
modifier: Modifier,
placeholderTextColor: Color,
Expand Down Expand Up @@ -331,14 +327,7 @@ private fun TextAreaDecorationBox(
},
modifier,
) { measurables, incomingConstraints ->
val leftPadding = contentPadding.calculateLeftPadding(layoutDirection)
val rightPadding = contentPadding.calculateRightPadding(layoutDirection)
val horizontalPadding = (leftPadding + rightPadding).roundToPx()
val verticalPadding =
(contentPadding.calculateTopPadding() + contentPadding.calculateBottomPadding()).roundToPx()

val textAreaConstraints =
incomingConstraints.offset(horizontal = -horizontalPadding, vertical = -verticalPadding).copy(minHeight = 0)
val textAreaConstraints = incomingConstraints.copy(minHeight = 0)

val textAreaPlaceable = measurables.single { it.layoutId == TEXT_AREA_ID }.measure(textAreaConstraints)

Expand All @@ -347,17 +336,14 @@ private fun TextAreaDecorationBox(
val placeholderPlaceable = measurables.find { it.layoutId == PLACEHOLDER_ID }?.measure(placeholderConstraints)

val width = calculateWidth(textAreaPlaceable, placeholderPlaceable, incomingConstraints)
val height = calculateHeight(textAreaPlaceable, placeholderPlaceable, verticalPadding, incomingConstraints)
val height = calculateHeight(textAreaPlaceable, placeholderPlaceable, incomingConstraints)

layout(width, height) {
val startPadding = contentPadding.calculateStartPadding(layoutDirection).roundToPx()
val topPadding = contentPadding.calculateTopPadding().roundToPx()

// Placed top-start
textAreaPlaceable.placeRelative(startPadding, topPadding)
textAreaPlaceable.placeRelative(0, 0)

// Placed similar to the input text above
placeholderPlaceable?.placeRelative(startPadding, topPadding)
placeholderPlaceable?.placeRelative(0, 0)
}
}
}
Expand All @@ -371,11 +357,10 @@ private fun calculateWidth(
private fun calculateHeight(
textFieldPlaceable: Placeable,
placeholderPlaceable: Placeable?,
verticalPadding: Int,
incomingConstraints: Constraints,
): Int {
val textAreaHeight = maxOf(textFieldPlaceable.height, placeholderPlaceable?.height ?: 0)
return (textAreaHeight + verticalPadding).coerceAtLeast(incomingConstraints.minHeight)
return textAreaHeight.coerceAtLeast(incomingConstraints.minHeight)
}

private const val PLACEHOLDER_ID = "Placeholder"
Expand Down

0 comments on commit 0816d43

Please sign in to comment.