package com.example.aiapp import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.unit.dp /** Which way a [Chevron] points. */ enum class Pointing { Up, Down, Left, Right, } /** * A chevron, pointing whichever of the four ways is asked for. * * Drawn rather than set in a font: a chevron from an icon font is one of the glyphs a system font * may simply not have, and the reader who gets an empty box instead is never the one who wrote it. * * One composable for all four directions rather than one per axis that differ by which coordinate * gets the minus sign -- the copies would drift, and the drift would be a bug in exactly one * direction. The shape is written once in its own coordinates, and [Pointing] is only a table of * how those map onto the box. * * It draws no label of its own, so every caller owes it a `contentDescription`. */ @Composable fun Chevron( pointing: Pointing, modifier: Modifier = Modifier, colour: Color = MaterialTheme.colorScheme.onSurfaceVariant, ) { val sideways = pointing == Pointing.Left || pointing == Pointing.Right Canvas( modifier .width(if (sideways) CHEVRON_DEPTH else CHEVRON_SPAN) .height(if (sideways) CHEVRON_SPAN else CHEVRON_DEPTH) ) { val inset = 2.dp.toPx() val wide = size.width - inset val tall = size.height - inset fun at(across: Float, along: Float) = when (pointing) { Pointing.Up -> Offset(lerp(inset, wide, across), lerp(tall, inset, along)) Pointing.Down -> Offset(lerp(inset, wide, across), lerp(inset, tall, along)) Pointing.Left -> Offset(lerp(wide, inset, along), lerp(inset, tall, across)) Pointing.Right -> Offset(lerp(inset, wide, along), lerp(inset, tall, across)) } val stroke = 2.dp.toPx() drawLine(colour, at(0f, 0f), at(0.5f, 1f), strokeWidth = stroke, cap = StrokeCap.Round) drawLine(colour, at(0.5f, 1f), at(1f, 0f), strokeWidth = stroke, cap = StrokeCap.Round) } } private fun lerp(from: Float, to: Float, fraction: Float) = from + (to - from) * fraction /** How far the chevron opens, across the direction it points. */ private val CHEVRON_SPAN = 20.dp /** How far it reaches in the direction it points. */ private val CHEVRON_DEPTH = 10.dp