Skip to content

Commit

Permalink
Use double arrows for breadcrumb bar scrollers
Browse files Browse the repository at this point in the history
For #8
  • Loading branch information
kirill-grouchnikov committed Jan 4, 2022
1 parent 65b8aca commit b93107d
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 26 deletions.
Expand Up @@ -37,9 +37,10 @@ import org.pushingpixels.aurora.common.AuroraInternalApi
import org.pushingpixels.aurora.common.withAlpha
import org.pushingpixels.aurora.component.model.*
import org.pushingpixels.aurora.component.projection.CommandButtonProjection
import org.pushingpixels.aurora.component.utils.TransitionAwarePainter
import org.pushingpixels.aurora.component.utils.TransitionAwarePainterDelegate
import org.pushingpixels.aurora.component.utils.*
import org.pushingpixels.aurora.component.utils.ArrowSizingConstants
import org.pushingpixels.aurora.component.utils.drawArrow
import org.pushingpixels.aurora.component.utils.drawDoubleArrow
import org.pushingpixels.aurora.theming.*

@OptIn(AuroraInternalApi::class)
Expand Down Expand Up @@ -88,26 +89,28 @@ fun AuroraBreadcrumbBar(commands: List<Command>, modifier: Modifier) {
icon = object : TransitionAwarePainterDelegate() {
override fun createNewIcon(modelStateInfoSnapshot: ModelStateInfoSnapshot): Painter {
return TransitionAwarePainter(
iconSize = ComboBoxSizingConstants.DefaultComboBoxArrowWidth,
iconSize = ArrowSizingConstants.DefaultDoubleArrowWidth,
decorationAreaType = decorationAreaType,
skinColors = colors,
modelStateInfoSnapshot = modelStateInfoSnapshot,
paintDelegate = { drawScope, iconSize, colorScheme ->
with(drawScope) {
val arrowWidth =
ComboBoxSizingConstants.DefaultComboBoxArrowHeight.toPx()
val arrowHeight =
ComboBoxSizingConstants.DefaultComboBoxArrowWidth.toPx()
val dx = (iconSize.toPx() - arrowWidth) / 2
val dy = (iconSize.toPx() - arrowHeight) / 2
val arrowDoubleWidth =
ArrowSizingConstants.DefaultDoubleArrowHeight.toPx() +
ArrowSizingConstants.DefaultDoubleArrowGap.toPx()
val arrowDoubleHeight =
ArrowSizingConstants.DefaultDoubleArrowWidth.toPx()
val dx = (iconSize.toPx() - arrowDoubleWidth) / 2
val dy = (iconSize.toPx() - arrowDoubleHeight) / 2
val alpha = if (modelStateInfoSnapshot.currModelState.isDisabled)
colors.getAlpha(decorationAreaType, modelStateInfoSnapshot.currModelState) else 1.0f
translate(left = dx, top = dy) {
drawArrow(
drawDoubleArrow(
drawScope = this,
width = arrowWidth,
height = arrowHeight,
strokeWidth = 2.0.dp.toPx(),
width = arrowDoubleWidth,
height = arrowDoubleHeight,
gap = ArrowSizingConstants.DefaultDoubleArrowGap.toPx(),
strokeWidth = ArrowSizingConstants.DefaultDoubleArrowStroke.toPx(),
direction = PopupPlacementStrategy.Startward,
layoutDirection = layoutDirection,
color = colorScheme.markColor.withAlpha(alpha)
Expand All @@ -131,26 +134,28 @@ fun AuroraBreadcrumbBar(commands: List<Command>, modifier: Modifier) {
icon = object : TransitionAwarePainterDelegate() {
override fun createNewIcon(modelStateInfoSnapshot: ModelStateInfoSnapshot): Painter {
return TransitionAwarePainter(
iconSize = ComboBoxSizingConstants.DefaultComboBoxArrowWidth,
iconSize = ArrowSizingConstants.DefaultDoubleArrowWidth,
decorationAreaType = decorationAreaType,
skinColors = colors,
modelStateInfoSnapshot = modelStateInfoSnapshot,
paintDelegate = { drawScope, iconSize, colorScheme ->
with(drawScope) {
val arrowWidth =
ComboBoxSizingConstants.DefaultComboBoxArrowHeight.toPx()
val arrowHeight =
ComboBoxSizingConstants.DefaultComboBoxArrowWidth.toPx()
val dx = (iconSize.toPx() - arrowWidth) / 2
val dy = (iconSize.toPx() - arrowHeight) / 2
val arrowDoubleWidth =
ArrowSizingConstants.DefaultDoubleArrowHeight.toPx() +
ArrowSizingConstants.DefaultDoubleArrowGap.toPx()
val arrowDoubleHeight =
ArrowSizingConstants.DefaultDoubleArrowWidth.toPx()
val dx = (iconSize.toPx() - arrowDoubleWidth) / 2
val dy = (iconSize.toPx() - arrowDoubleHeight) / 2
val alpha = if (modelStateInfoSnapshot.currModelState.isDisabled)
colors.getAlpha(decorationAreaType, modelStateInfoSnapshot.currModelState) else 1.0f
translate(left = dx, top = dy) {
drawArrow(
drawDoubleArrow(
drawScope = this,
width = arrowWidth,
height = arrowHeight,
strokeWidth = 2.0.dp.toPx(),
width = arrowDoubleWidth,
height = arrowDoubleHeight,
gap = ArrowSizingConstants.DefaultDoubleArrowGap.toPx(),
strokeWidth = ArrowSizingConstants.DefaultDoubleArrowStroke.toPx(),
direction = PopupPlacementStrategy.Endward,
layoutDirection = layoutDirection,
color = colorScheme.markColor.withAlpha(alpha)
Expand Down
Expand Up @@ -409,7 +409,7 @@ internal fun <E> AuroraComboBox(
drawScope = this,
width = arrowWidth,
height = arrowHeight,
strokeWidth = 2.0.dp.toPx(),
strokeWidth = ArrowSizingConstants.DefaultArrowStroke.toPx(),
direction = presentationModel.popupPlacementStrategy,
layoutDirection = layoutDirection,
color = arrowColor.withAlpha(alpha)
Expand Down
Expand Up @@ -1500,7 +1500,7 @@ private fun CommandButtonPopupIconContent(
drawScope = this,
width = arrowWidth,
height = arrowHeight,
strokeWidth = 2.0.dp.toPx(),
strokeWidth = ArrowSizingConstants.DefaultArrowStroke.toPx(),
direction = presentationModel.popupPlacementStrategy,
layoutDirection = layoutDirection,
color = arrowColor
Expand Down
Expand Up @@ -24,8 +24,17 @@ import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import org.pushingpixels.aurora.theming.PopupPlacementStrategy

internal object ArrowSizingConstants {
val DefaultArrowStroke = 2.0.dp
val DefaultDoubleArrowWidth = 8.dp
val DefaultDoubleArrowHeight = 5.dp
val DefaultDoubleArrowStroke = 1.5.dp
val DefaultDoubleArrowGap = 3.0.dp
}

internal fun drawArrow(
drawScope: DrawScope,
width: Float, height: Float, strokeWidth: Float,
Expand Down Expand Up @@ -96,3 +105,67 @@ internal fun drawArrow(
}
}

internal fun drawDoubleArrow(
drawScope: DrawScope,
width: Float, height: Float, gap: Float, strokeWidth: Float,
direction: PopupPlacementStrategy, layoutDirection: LayoutDirection,
color: Color
) {
require(direction != PopupPlacementStrategy.CenteredVertically) {
"CenteredVertically not supported for double arrows"
}

val cushion = strokeWidth / 2.0f
val gp = Path()

if (direction == PopupPlacementStrategy.Downward) {
// top part
gp.moveTo(cushion, cushion)
gp.lineTo(0.5f * width, height - gap - cushion - 1)
gp.lineTo(width - cushion, cushion)
// bottom part
gp.moveTo(cushion, gap + cushion)
gp.lineTo(0.5f * width, height - cushion - 1)
gp.lineTo(width - cushion, gap + cushion)
} else if (direction == PopupPlacementStrategy.Upward) {
// top part
gp.moveTo(cushion, height - gap - cushion - 1)
gp.lineTo(0.5f * width, cushion)
gp.lineTo(width - cushion, height - gap - cushion - 1)
// bottom part
gp.moveTo(cushion, height - cushion - 1)
gp.lineTo(0.5f * width, gap + cushion)
gp.lineTo(width - cushion, height - cushion - 1)
} else {
val leftward =
((direction == PopupPlacementStrategy.Startward) && (layoutDirection == LayoutDirection.Ltr)) ||
((direction == PopupPlacementStrategy.Endward) && (layoutDirection == LayoutDirection.Rtl))
if (leftward) {
// left part
gp.moveTo(width - gap - 1 - cushion, cushion)
gp.lineTo(cushion, 0.5f * height)
gp.lineTo(width - gap - 1 - cushion, height - cushion)
// right part
gp.moveTo(width - 1 - cushion, cushion)
gp.lineTo(gap + cushion, 0.5f * height)
gp.lineTo(width - 1 - cushion, height - cushion)
} else {
// left part
gp.moveTo(cushion, cushion)
gp.lineTo(width - gap - 1 - cushion, 0.5f * height)
gp.lineTo(cushion, height - cushion)
// right part
gp.moveTo(gap + cushion, cushion)
gp.lineTo(width - 1 - cushion, 0.5f * height)
gp.lineTo(gap + cushion, height - cushion)
}
}

with(drawScope) {
drawPath(
path = gp,
color = color,
style = Stroke(width = strokeWidth, cap = StrokeCap.Round, join = StrokeJoin.Miter)
)
}
}

0 comments on commit b93107d

Please sign in to comment.