diff --git a/CHANGELOG.md b/CHANGELOG.md index e8babc261..e30134051 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,12 @@ New: - Add `linuxArm64` target. - Add `rrtop` sample. +- Support true color palette. Changed: - Disable klib signature clash checks for JS compilations. These occasionally occur as a result of Compose compiler behavior, and are safe to disable (the first-party JetBrains Compose Gradle plugin also disables them). - Remove `Terminal$Size` and use `IntSize` instead in `Terminal#size` for optimization purposes. +- Remove Color.Bright* constants. Use Color to create the desired color. Fixed: - Use CRLF line endings to fix rendering when a terminal is in raw mode. diff --git a/mosaic-runtime/api/mosaic-runtime.api b/mosaic-runtime/api/mosaic-runtime.api index 4cdc351a2..d741607b7 100644 --- a/mosaic-runtime/api/mosaic-runtime.api +++ b/mosaic-runtime/api/mosaic-runtime.api @@ -30,7 +30,7 @@ public final class com/jakewharton/mosaic/layout/AspectRatioKt { } public final class com/jakewharton/mosaic/layout/BackgroundKt { - public static final fun background (Lcom/jakewharton/mosaic/modifier/Modifier;Lcom/jakewharton/mosaic/ui/Color;)Lcom/jakewharton/mosaic/modifier/Modifier; + public static final fun background-fCupJr8 (Lcom/jakewharton/mosaic/modifier/Modifier;I)Lcom/jakewharton/mosaic/modifier/Modifier; } public abstract interface class com/jakewharton/mosaic/layout/ContentDrawScope : com/jakewharton/mosaic/layout/DrawScope { @@ -47,12 +47,12 @@ public final class com/jakewharton/mosaic/layout/DrawModifierKt { } public abstract interface class com/jakewharton/mosaic/layout/DrawScope { - public abstract fun drawRect (Lcom/jakewharton/mosaic/ui/Color;IIII)V - public static synthetic fun drawRect$default (Lcom/jakewharton/mosaic/layout/DrawScope;Lcom/jakewharton/mosaic/ui/Color;IIIIILjava/lang/Object;)V - public abstract fun drawText (IILcom/jakewharton/mosaic/text/AnnotatedString;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;)V - public abstract fun drawText (IILjava/lang/String;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;)V - public static synthetic fun drawText$default (Lcom/jakewharton/mosaic/layout/DrawScope;IILcom/jakewharton/mosaic/text/AnnotatedString;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;ILjava/lang/Object;)V - public static synthetic fun drawText$default (Lcom/jakewharton/mosaic/layout/DrawScope;IILjava/lang/String;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;ILjava/lang/Object;)V + public abstract fun drawRect-e5kUBSE (IIIII)V + public static synthetic fun drawRect-e5kUBSE$default (Lcom/jakewharton/mosaic/layout/DrawScope;IIIIIILjava/lang/Object;)V + public abstract fun drawText-HJtvjdw (IILcom/jakewharton/mosaic/text/AnnotatedString;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;)V + public abstract fun drawText-HJtvjdw (IILjava/lang/String;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;)V + public static synthetic fun drawText-HJtvjdw$default (Lcom/jakewharton/mosaic/layout/DrawScope;IILcom/jakewharton/mosaic/text/AnnotatedString;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;ILjava/lang/Object;)V + public static synthetic fun drawText-HJtvjdw$default (Lcom/jakewharton/mosaic/layout/DrawScope;IILjava/lang/String;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;ILjava/lang/Object;)V public abstract fun getHeight ()I public abstract fun getWidth ()I } @@ -268,14 +268,13 @@ public final class com/jakewharton/mosaic/text/AnnotatedStringKt { public final class com/jakewharton/mosaic/text/SpanStyle { public static final field $stable I - public fun ()V - public fun (Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Lcom/jakewharton/mosaic/ui/Color;)V public synthetic fun (Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Lcom/jakewharton/mosaic/ui/Color;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun copy (Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Lcom/jakewharton/mosaic/ui/Color;)Lcom/jakewharton/mosaic/text/SpanStyle; - public static synthetic fun copy$default (Lcom/jakewharton/mosaic/text/SpanStyle;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Lcom/jakewharton/mosaic/ui/Color;ILjava/lang/Object;)Lcom/jakewharton/mosaic/text/SpanStyle; + public synthetic fun (Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Lcom/jakewharton/mosaic/ui/Color;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun copy-0C4kZ_4 (Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Lcom/jakewharton/mosaic/ui/Color;)Lcom/jakewharton/mosaic/text/SpanStyle; + public static synthetic fun copy-0C4kZ_4$default (Lcom/jakewharton/mosaic/text/SpanStyle;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Lcom/jakewharton/mosaic/ui/Color;ILjava/lang/Object;)Lcom/jakewharton/mosaic/text/SpanStyle; public fun equals (Ljava/lang/Object;)Z - public final fun getBackground ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getColor ()Lcom/jakewharton/mosaic/ui/Color; + public final fun getBackground-xbxrsts ()Lcom/jakewharton/mosaic/ui/Color; + public final fun getColor-xbxrsts ()Lcom/jakewharton/mosaic/ui/Color; public final fun getTextStyle ()Lcom/jakewharton/mosaic/ui/TextStyle; public fun hashCode ()I public final fun merge (Lcom/jakewharton/mosaic/text/SpanStyle;)Lcom/jakewharton/mosaic/text/SpanStyle; @@ -404,28 +403,32 @@ public abstract interface class com/jakewharton/mosaic/ui/BoxScope { } public final class com/jakewharton/mosaic/ui/Color { - public static final field $stable I public static final field Companion Lcom/jakewharton/mosaic/ui/Color$Companion; + public static final synthetic fun box-impl (I)Lcom/jakewharton/mosaic/ui/Color; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (ILjava/lang/Object;)Z + public static final fun equals-impl0 (II)Z + public fun hashCode ()I + public static fun hashCode-impl (I)I public fun toString ()Ljava/lang/String; + public static fun toString-impl (I)Ljava/lang/String; + public final synthetic fun unbox-impl ()I } public final class com/jakewharton/mosaic/ui/Color$Companion { - public final fun getBlack ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getBlue ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getBrightBlack ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getBrightBlue ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getBrightCyan ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getBrightGreen ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getBrightMagenta ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getBrightRed ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getBrightWhite ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getBrightYellow ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getCyan ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getGreen ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getMagenta ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getRed ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getWhite ()Lcom/jakewharton/mosaic/ui/Color; - public final fun getYellow ()Lcom/jakewharton/mosaic/ui/Color; + public final fun getBlack-OrXnJU4 ()I + public final fun getBlue-OrXnJU4 ()I + public final fun getCyan-OrXnJU4 ()I + public final fun getGreen-OrXnJU4 ()I + public final fun getMagenta-OrXnJU4 ()I + public final fun getRed-OrXnJU4 ()I + public final fun getWhite-OrXnJU4 ()I + public final fun getYellow-OrXnJU4 ()I +} + +public final class com/jakewharton/mosaic/ui/ColorKt { + public static final fun Color (FFF)I + public static final fun Color (III)I } public final class com/jakewharton/mosaic/ui/Column { @@ -460,7 +463,7 @@ public final class com/jakewharton/mosaic/ui/ComposableSingletons$SpacerKt { } public final class com/jakewharton/mosaic/ui/FillerKt { - public static final fun Filler (CLcom/jakewharton/mosaic/modifier/Modifier;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Landroidx/compose/runtime/Composer;II)V + public static final fun Filler-g8kd68k (CLcom/jakewharton/mosaic/modifier/Modifier;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Landroidx/compose/runtime/Composer;II)V } public final class com/jakewharton/mosaic/ui/Layout { @@ -492,8 +495,8 @@ public final class com/jakewharton/mosaic/ui/Static { } public final class com/jakewharton/mosaic/ui/Text { - public static final fun Text (Lcom/jakewharton/mosaic/text/AnnotatedString;Lcom/jakewharton/mosaic/modifier/Modifier;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Landroidx/compose/runtime/Composer;II)V - public static final fun Text (Ljava/lang/String;Lcom/jakewharton/mosaic/modifier/Modifier;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Landroidx/compose/runtime/Composer;II)V + public static final fun Text-g8kd68k (Lcom/jakewharton/mosaic/text/AnnotatedString;Lcom/jakewharton/mosaic/modifier/Modifier;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Landroidx/compose/runtime/Composer;II)V + public static final fun Text-g8kd68k (Ljava/lang/String;Lcom/jakewharton/mosaic/modifier/Modifier;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/Color;Lcom/jakewharton/mosaic/ui/TextStyle;Landroidx/compose/runtime/Composer;II)V } public final class com/jakewharton/mosaic/ui/TextStyle { diff --git a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ansi.kt b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ansi.kt index cca54b9d1..9f29ea69b 100644 --- a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ansi.kt +++ b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ansi.kt @@ -1,4 +1,71 @@ package com.jakewharton.mosaic -internal const val clearLine = "\u001B[K" -internal const val cursorUp = "\u001B[F" +import com.github.ajalt.mordant.rendering.AnsiLevel as MordantAnsiLevel +import com.jakewharton.mosaic.ui.AnsiLevel +import com.jakewharton.mosaic.ui.Color +import kotlin.math.roundToInt + +private const val ESC = "\u001B" +internal const val CSI = "$ESC[" + +internal const val ansiReset = "${CSI}0" +internal const val clearLine = "${CSI}K" +internal const val cursorUp = "${CSI}F" + +internal const val ansiSeparator = ";" +internal const val ansiClosingCharacter = "m" + +internal const val ansiFgColorSelector = 38 +internal const val ansiFgColorReset = 39 +internal const val ansiFgColorOffset = 0 + +internal const val ansiBgColorSelector = 48 +internal const val ansiBgColorReset = 49 +internal const val ansiBgColorOffset = 10 + +internal const val ansiSelectorColor256 = 5 +internal const val ansiSelectorColorRgb = 2 + +internal fun MordantAnsiLevel.toMosaicAnsiLevel(): AnsiLevel { + return when (this) { + MordantAnsiLevel.NONE -> AnsiLevel.NONE + MordantAnsiLevel.ANSI16 -> AnsiLevel.ANSI16 + MordantAnsiLevel.ANSI256 -> AnsiLevel.ANSI256 + MordantAnsiLevel.TRUECOLOR -> AnsiLevel.TRUECOLOR + } +} + +// simpler version without full conversion to HSV +// https://github.com/ajalt/colormath/blob/4a0cc9796c743cb4965407204ee63b40aaf22fca/colormath/src/commonMain/kotlin/com/github/ajalt/colormath/model/RGB.kt#L301 +internal fun Color.toAnsi16Code(): Int { + val value = (maxOf(redFloat, greenFloat, blueFloat) * 100).roundToInt() + if (value == 30) { + return 30 + } + val v = value / 50 + val ansiCode = 30 + ( + (blueFloat.roundToInt() * 4) + or (greenFloat.roundToInt() * 2) + or redFloat.roundToInt() + ) + return if (v == 2) ansiCode + 60 else ansiCode +} + +// https://github.com/ajalt/colormath/blob/4a0cc9796c743cb4965407204ee63b40aaf22fca/colormath/src/commonMain/kotlin/com/github/ajalt/colormath/model/RGB.kt#L310 +internal fun Color.toAnsi256Code(): Int { + val ri = redInt + val gi = greenInt + val bi = blueInt + // grayscale + return if (ri == gi && gi == bi) { + when { + ri < 8 -> 16 + ri > 248 -> 231 + else -> (((ri - 8) / 247.0) * 24.0).roundToInt() + 232 + } + } else { + 16 + (36 * (redFloat * 5).roundToInt()) + + (6 * (greenFloat * 5).roundToInt()) + + (blueFloat * 5).roundToInt() + } +} diff --git a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/canvas.kt b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/canvas.kt index 68da04c10..48ba2f4a7 100644 --- a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/canvas.kt +++ b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/canvas.kt @@ -1,5 +1,6 @@ package com.jakewharton.mosaic +import com.jakewharton.mosaic.ui.AnsiLevel import com.jakewharton.mosaic.ui.Color import com.jakewharton.mosaic.ui.TextStyle import com.jakewharton.mosaic.ui.TextStyle.Companion.Bold @@ -24,6 +25,7 @@ private val blankPixel = TextPixel(' ') internal class TextSurface( override val width: Int, override val height: Int, + private val ansiLevel: AnsiLevel, ) : TextCanvas { override var translationX = 0 override var translationY = 0 @@ -40,33 +42,53 @@ internal class TextSurface( var lastPixel = blankPixel for (columnIndex in 0 until width) { val pixel = rowPixels[columnIndex] - if (pixel.foreground != lastPixel.foreground) { - attributes += pixel.foreground?.fg ?: 39 - } - if (pixel.background != lastPixel.background) { - attributes += pixel.background?.bg ?: 49 - } - fun maybeToggleStyle(style: TextStyle, on: Int, off: Int) { - if (style in pixel.style) { - if (style !in lastPixel.style) { - attributes += on + if (ansiLevel != AnsiLevel.NONE) { + if (pixel.foreground != lastPixel.foreground) { + attributes.addColor( + pixel.foreground, + ansiLevel, + ansiFgColorSelector, + ansiFgColorReset, + ansiFgColorOffset, + ) + } + if (pixel.background != lastPixel.background) { + attributes.addColor( + pixel.background, + ansiLevel, + ansiBgColorSelector, + ansiBgColorReset, + ansiBgColorOffset, + ) + } + + fun maybeToggleStyle(style: TextStyle, on: Int, off: Int) { + if (style in pixel.style) { + if (style !in lastPixel.style) { + attributes += on + } + } else if (style in lastPixel.style) { + attributes += off } - } else if (style in lastPixel.style) { - attributes += off } - } - if (pixel.style != lastPixel.style) { - maybeToggleStyle(Bold, 1, 22) - maybeToggleStyle(Dim, 2, 22) - maybeToggleStyle(Italic, 3, 23) - maybeToggleStyle(Underline, 4, 24) - maybeToggleStyle(Invert, 7, 27) - maybeToggleStyle(Strikethrough, 9, 29) - } - if (attributes.isNotEmpty()) { - attributes.joinTo(appendable, separator = ";", prefix = "\u001B[", postfix = "m") - attributes.clear() // This list is reused! + if (pixel.style != lastPixel.style) { + maybeToggleStyle(Bold, 1, 22) + maybeToggleStyle(Dim, 2, 22) + maybeToggleStyle(Italic, 3, 23) + maybeToggleStyle(Underline, 4, 24) + maybeToggleStyle(Invert, 7, 27) + maybeToggleStyle(Strikethrough, 9, 29) + } + if (attributes.isNotEmpty()) { + attributes.joinTo( + appendable, + separator = ansiSeparator, + prefix = CSI, + postfix = ansiClosingCharacter, + ) + attributes.clear() // This list is reused! + } } appendable.append(pixel.value) @@ -77,7 +99,44 @@ internal class TextSurface( lastPixel.foreground != null || lastPixel.style != None ) { - appendable.append("\u001B[0m") + appendable.append(ansiReset) + appendable.append(ansiClosingCharacter) + } + } + + private fun MutableList.addColor( + color: Color?, + ansiLevel: AnsiLevel, + select: Int, + reset: Int, + offset: Int, + ) { + if (color == null) { + add(reset) + return + } + when (ansiLevel) { + AnsiLevel.NONE -> add(reset) + AnsiLevel.ANSI16 -> { + val ansi16Code = color.toAnsi16Code() + if (ansi16Code == ansiFgColorReset || ansi16Code == ansiBgColorReset) { + add(reset) + } else { + add(ansi16Code + offset) + } + } + AnsiLevel.ANSI256 -> { + add(select) + add(ansiSelectorColor256) + add(color.toAnsi256Code()) + } + AnsiLevel.TRUECOLOR -> { + add(select) + add(ansiSelectorColorRgb) + add(color.redInt) + add(color.greenInt) + add(color.blueInt) + } } } diff --git a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/layout/Node.kt b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/layout/Node.kt index dbbd4e389..5aa605530 100644 --- a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/layout/Node.kt +++ b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/layout/Node.kt @@ -4,6 +4,7 @@ import com.jakewharton.mosaic.TextCanvas import com.jakewharton.mosaic.TextSurface import com.jakewharton.mosaic.layout.Placeable.PlacementScope import com.jakewharton.mosaic.modifier.Modifier +import com.jakewharton.mosaic.ui.AnsiLevel import com.jakewharton.mosaic.ui.unit.Constraints internal fun interface DebugPolicy { @@ -135,8 +136,8 @@ internal class MosaicNode( * Draw this node to a [TextSurface]. * A call to [measureAndPlace] must precede calls to this function. */ - fun paint(): TextSurface { - val surface = TextSurface(width, height) + fun paint(ansiLevel: AnsiLevel): TextSurface { + val surface = TextSurface(width, height, ansiLevel) topLayer.drawTo(surface) return surface } @@ -145,12 +146,12 @@ internal class MosaicNode( * Append any static [TextSurfaces][TextSurface] to [statics]. * A call to [measureAndPlace] must precede calls to this function. */ - fun paintStatics(statics: MutableList) { + fun paintStatics(statics: MutableList, ansiLevel: AnsiLevel) { for (child in children) { if (isStatic) { - statics += child.paint() + statics += child.paint(ansiLevel) } - child.paintStatics(statics) + child.paintStatics(statics, ansiLevel) } onStaticDraw?.invoke() } diff --git a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/mosaic.kt b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/mosaic.kt index e321684d7..ac53e2ee4 100644 --- a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/mosaic.kt +++ b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/mosaic.kt @@ -56,11 +56,13 @@ public interface MosaicScope : CoroutineScope { } public suspend fun runMosaic(body: suspend MosaicScope.() -> Unit): Unit = coroutineScope { + val terminal = MordantTerminal() + val rendering = if (debugOutput) { @OptIn(ExperimentalTime::class) // Not used in production. - DebugRendering() + DebugRendering(ansiLevel = terminal.info.ansiLevel.toMosaicAnsiLevel()) } else { - AnsiRendering() + AnsiRendering(ansiLevel = terminal.info.ansiLevel.toMosaicAnsiLevel()) } var hasFrameWaiters = false @@ -96,7 +98,6 @@ public suspend fun runMosaic(body: suspend MosaicScope.() -> Unit): Unit = corou } } - val terminal = MordantTerminal() val terminalInfo = mutableStateOf( Terminal( size = IntSize(terminal.info.width, terminal.info.height), diff --git a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/rendering.kt b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/rendering.kt index 79001cb83..af26f016d 100644 --- a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/rendering.kt +++ b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/rendering.kt @@ -1,6 +1,7 @@ package com.jakewharton.mosaic import com.jakewharton.mosaic.layout.MosaicNode +import com.jakewharton.mosaic.ui.AnsiLevel import kotlin.time.ExperimentalTime import kotlin.time.TimeMark import kotlin.time.TimeSource @@ -18,6 +19,7 @@ internal interface Rendering { @ExperimentalTime internal class DebugRendering( private val systemClock: TimeSource = TimeSource.Monotonic, + private val ansiLevel: AnsiLevel = AnsiLevel.TRUECOLOR, ) : Rendering { private var lastRender: TimeMark? = null @@ -38,7 +40,7 @@ internal class DebugRendering( try { val statics = ArrayList() - .also { node.paintStatics(it) } + .also { node.paintStatics(it, ansiLevel) } .map { it.render() } if (statics.isNotEmpty()) { appendLine("STATIC:") @@ -55,7 +57,7 @@ internal class DebugRendering( appendLine("OUTPUT:") try { - appendLine(node.paint().render()) + appendLine(node.paint(ansiLevel).render()) } catch (t: Throwable) { failed = true append(t.stackTraceToString()) @@ -68,7 +70,9 @@ internal class DebugRendering( } } -internal class AnsiRendering : Rendering { +internal class AnsiRendering( + private val ansiLevel: AnsiLevel = AnsiLevel.TRUECOLOR, +) : Rendering { private val stringBuilder = StringBuilder(100) private val staticSurfaces = ArrayList() private var lastHeight = 0 @@ -95,13 +99,13 @@ internal class AnsiRendering : Rendering { node.measureAndPlace() - node.paintStatics(staticSurfaces) + node.paintStatics(staticSurfaces, ansiLevel) for (staticSurface in staticSurfaces) { appendSurface(staticSurface) } staticSurfaces.clear() - val surface = node.paint() + val surface = node.paint(ansiLevel) appendSurface(surface) // If the new output contains fewer lines than the last output, clear those old lines. diff --git a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ui/AnsiLevel.kt b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ui/AnsiLevel.kt new file mode 100644 index 000000000..e2ac0d058 --- /dev/null +++ b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ui/AnsiLevel.kt @@ -0,0 +1,8 @@ +package com.jakewharton.mosaic.ui + +internal enum class AnsiLevel { + NONE, + ANSI16, + ANSI256, + TRUECOLOR, +} diff --git a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ui/Color.kt b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ui/Color.kt index c78a7ab3c..edb815b59 100644 --- a/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ui/Color.kt +++ b/mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ui/Color.kt @@ -2,61 +2,155 @@ package com.jakewharton.mosaic.ui import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable +import kotlin.jvm.JvmInline @Immutable -public class Color private constructor( - internal val fg: Int, - internal val bg: Int, +@JvmInline +public value class Color internal constructor( + private val value: Int, ) { - override fun toString(): String = "Color($fg)" + override fun toString(): String = "Color($redInt, $greenInt, $blueInt)" + + /** + * Returns the value of the red component as integer between 0 and 255. + * + * @see redFloat + * + * @see blueInt + * @see greenInt + */ + @Stable + internal val redInt: Int + get() = ((value shr 16) and 0xFF) + + /** + * Returns the value of the red component as float between 0.0 and 1.0. + * + * @see redInt + * + * @see blueFloat + * @see greenFloat + */ + @Stable + internal val redFloat: Float + get() = redInt / 255.0f + + /** + * Returns the value of the green component as integer between 0 and 255. + * + * @see greenFloat + * + * @see redInt + * @see blueInt + */ + @Stable + internal val greenInt: Int + get() = ((value shr 8) and 0xFF) + + /** + * Returns the value of the green component as float between 0.0 and 1.0. + * + * @see greenInt + * + * @see redFloat + * @see blueFloat + */ + @Stable + internal val greenFloat: Float + get() = greenInt / 255.0f + + /** + * Returns the value of the blue component as integer between 0 and 255. + * + * @see blueFloat + * + * @see redInt + * @see greenInt + */ + @Stable + internal val blueInt: Int + inline get() = (value and 0xFF) + + /** + * Returns the value of the blue component as float between 0.0 and 1.0. + * + * @see blueInt + * + * @see redFloat + * @see greenFloat + */ + @Stable + internal val blueFloat: Float + get() = blueInt / 255.0f public companion object { @Stable - public val Black: Color = Color(30, 40) + public val Black: Color = Color(0x000000) @Stable - public val Red: Color = Color(31, 41) + public val Red: Color = Color(0xFF0000) @Stable - public val Green: Color = Color(32, 42) + public val Green: Color = Color(0x00FF00) @Stable - public val Yellow: Color = Color(33, 43) + public val Blue: Color = Color(0x0000FF) @Stable - public val Blue: Color = Color(34, 44) + public val Yellow: Color = Color(0xFFFF00) @Stable - public val Magenta: Color = Color(35, 45) + public val Magenta: Color = Color(0xFF00FF) @Stable - public val Cyan: Color = Color(36, 46) + public val Cyan: Color = Color(0x00FFFF) @Stable - public val White: Color = Color(37, 47) - - @Stable - public val BrightBlack: Color = Color(90, 100) - - @Stable - public val BrightRed: Color = Color(91, 101) - - @Stable - public val BrightGreen: Color = Color(92, 102) - - @Stable - public val BrightYellow: Color = Color(93, 103) - - @Stable - public val BrightBlue: Color = Color(94, 104) - - @Stable - public val BrightMagenta: Color = Color(95, 105) + public val White: Color = Color(0xFFFFFF) + } +} - @Stable - public val BrightCyan: Color = Color(96, 106) +/** + * Creates a new [Color] instance from an RGB color components. + * + * @param red The red component of the color, between 0.0 and 1.0. + * @param green The green component of the color, between 0.0 and 1.0. + * @param blue The blue component of the color, between 0.0 and 1.0. + * + * @return A non-null instance of [Color] + */ +@Stable +public fun Color(red: Float, green: Float, blue: Float): Color { + require(red in 0.0f..1.0f) + require(green in 0.0f..1.0f) + require(blue in 0.0f..1.0f) + + return Color( + red = (red * 255.0f + 0.5f).toInt(), + green = (green * 255.0f + 0.5f).toInt(), + blue = (blue * 255.0f + 0.5f).toInt(), + ) +} - @Stable - public val BrightWhite: Color = Color(97, 107) - } +/** + * Creates a new [Color] instance from an RGB color components. + * + * @param red The red component of the color, between 0 and 255. + * @param green The green component of the color, between 0 and 255. + * @param blue The blue component of the color, between 0 and 255. + * + * @return A non-null instance of [Color] + */ +@Stable +public fun Color(red: Int, green: Int, blue: Int): Color { + require(red in 0..0xFF) + require(green in 0..0xFF) + require(blue in 0..0xFF) + + val rgb = + ((red and 0xFF) shl 16) or + ((green and 0xFF) shl 8) or + (blue and 0xFF) + + return Color(rgb) } diff --git a/samples/demo/src/main/kotlin/example/demo.kt b/samples/demo/src/main/kotlin/example/demo.kt index 1ba09ce85..61d29199b 100644 --- a/samples/demo/src/main/kotlin/example/demo.kt +++ b/samples/demo/src/main/kotlin/example/demo.kt @@ -1,38 +1,103 @@ package example +import androidx.compose.runtime.Composable import com.jakewharton.mosaic.LocalTerminal +import com.jakewharton.mosaic.layout.background +import com.jakewharton.mosaic.layout.height +import com.jakewharton.mosaic.layout.size +import com.jakewharton.mosaic.modifier.Modifier import com.jakewharton.mosaic.runMosaicBlocking import com.jakewharton.mosaic.text.SpanStyle import com.jakewharton.mosaic.text.buildAnnotatedString import com.jakewharton.mosaic.text.withStyle +import com.jakewharton.mosaic.ui.Box import com.jakewharton.mosaic.ui.Color +import com.jakewharton.mosaic.ui.Column +import com.jakewharton.mosaic.ui.Filler +import com.jakewharton.mosaic.ui.Row +import com.jakewharton.mosaic.ui.Spacer import com.jakewharton.mosaic.ui.Text import kotlinx.coroutines.suspendCancellableCoroutine +private val BrightGreen = Color(100, 255, 100) +private val BrightBlue = Color(60, 140, 230) + fun main() = runMosaicBlocking { setContent { - val terminal = LocalTerminal.current - Text( - buildAnnotatedString { - append("Terminal(") - withStyle(SpanStyle(color = Color.BrightGreen)) { - append("width=") - } - withStyle(SpanStyle(color = Color.BrightBlue)) { - append(terminal.size.width.toString()) - } - append(", ") - withStyle(SpanStyle(color = Color.BrightGreen)) { - append("height=") - } - withStyle(SpanStyle(color = Color.BrightBlue)) { - append(terminal.size.height.toString()) - } - append(")") - }, - ) + Column { + val terminal = LocalTerminal.current + Text( + buildAnnotatedString { + append("Terminal(") + withStyle(SpanStyle(color = BrightGreen)) { + append("width=") + } + withStyle(SpanStyle(color = BrightBlue)) { + append(terminal.size.width.toString()) + } + append(", ") + withStyle(SpanStyle(color = BrightGreen)) { + append("height=") + } + withStyle(SpanStyle(color = BrightBlue)) { + append(terminal.size.height.toString()) + } + append(")") + }, + ) + Spacer(modifier = Modifier.height(1)) + Gradient( + repeatedWord = "Red", + textColorProvider = { percent -> Color(1.0f - percent, 0.0f, 0.0f) }, + backgroundColorProvider = { percent -> Color(percent, 0.0f, 0.0f) }, + ) + Gradient( + repeatedWord = "Green", + textColorProvider = { percent -> Color(0.0f, 1.0f - percent, 0.0f) }, + backgroundColorProvider = { percent -> Color(0.0f, percent, 0.0f) }, + ) + Gradient( + repeatedWord = "Blue", + textColorProvider = { percent -> Color(0.0f, 0.0f, 1.0f - percent) }, + backgroundColorProvider = { percent -> Color(0.0f, 0.0f, percent) }, + ) + } } // Run forever! suspendCancellableCoroutine { } } + +@Composable +private fun Gradient( + repeatedWord: String, + textColorProvider: (percent: Float) -> Color, + backgroundColorProvider: (percent: Float) -> Color, +) { + val width = LocalTerminal.current.size.width / 2 + Box { + Row { + var wordCharIndex = 0 + repeat(width) { index -> + if (wordCharIndex == repeatedWord.length) { + wordCharIndex = 0 + } + Filler( + char = repeatedWord[wordCharIndex], + foreground = textColorProvider.invoke(index / width.toFloat()), + modifier = Modifier.size(1), + ) + wordCharIndex++ + } + } + Row { + repeat(width) { index -> + Spacer( + modifier = Modifier + .size(1) + .background(backgroundColorProvider.invoke(index / width.toFloat())), + ) + } + } + } +} diff --git a/samples/jest/src/main/kotlin/example/jest.kt b/samples/jest/src/main/kotlin/example/jest.kt index ab106d471..b22a8d4cf 100644 --- a/samples/jest/src/main/kotlin/example/jest.kt +++ b/samples/jest/src/main/kotlin/example/jest.kt @@ -17,8 +17,8 @@ import com.jakewharton.mosaic.runMosaicBlocking import com.jakewharton.mosaic.text.SpanStyle import com.jakewharton.mosaic.text.buildAnnotatedString import com.jakewharton.mosaic.text.withStyle +import com.jakewharton.mosaic.ui.Color import com.jakewharton.mosaic.ui.Color.Companion.Black -import com.jakewharton.mosaic.ui.Color.Companion.BrightBlack import com.jakewharton.mosaic.ui.Color.Companion.Green import com.jakewharton.mosaic.ui.Color.Companion.Red import com.jakewharton.mosaic.ui.Color.Companion.Yellow @@ -35,6 +35,8 @@ import kotlinx.coroutines.CoroutineStart.UNDISPATCHED import kotlinx.coroutines.delay import kotlinx.coroutines.launch +private val Gray = Color(128, 128, 128) + fun main() = runMosaicBlocking { val paths = ArrayDeque( listOf( @@ -245,7 +247,7 @@ fun TestProgress(totalTests: Int, passed: Int, failed: Int, running: Int) { withStyle(SpanStyle(background = Yellow)) { append(" ".repeat(runningWidth)) } - withStyle(SpanStyle(background = BrightBlack)) { + withStyle(SpanStyle(background = Gray)) { append(" ".repeat(totalWidth - failedWidth - passedWidth - runningWidth)) } }, diff --git a/samples/rrtop/src/main/kotlin/example/RrtopApp.kt b/samples/rrtop/src/main/kotlin/example/RrtopApp.kt index bb1677748..8de8c0b2a 100644 --- a/samples/rrtop/src/main/kotlin/example/RrtopApp.kt +++ b/samples/rrtop/src/main/kotlin/example/RrtopApp.kt @@ -1,10 +1,12 @@ package example import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import com.jakewharton.mosaic.LocalTerminal +import com.jakewharton.mosaic.layout.background import com.jakewharton.mosaic.layout.fillMaxWidth import com.jakewharton.mosaic.layout.height import com.jakewharton.mosaic.layout.padding @@ -15,7 +17,6 @@ import com.jakewharton.mosaic.text.buildAnnotatedString import com.jakewharton.mosaic.text.withStyle import com.jakewharton.mosaic.ui.Alignment import com.jakewharton.mosaic.ui.Box -import com.jakewharton.mosaic.ui.Color import com.jakewharton.mosaic.ui.Text import example.common.Key import example.common.key @@ -30,44 +31,47 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @Composable -fun RrtopApp(rrtopViewModel: RrtopViewModel) { +fun RrtopApp(rrtopViewModel: RrtopViewModel, colorsPalette: RrtopColorsPalette) { val terminal = LocalTerminal.current val rrtopUiState by rrtopViewModel.uiStateFlow.collectAsState() - Box( - modifier = Modifier - .width(terminal.size.width) - .height(terminal.size.height - 1), // subtraction of one is necessary, because there is a line with a cursor at the bottom, which moves up all the content - ) { - when (rrtopUiState.currentScreen) { - RrtopUiState.Screen.Main -> MainScreen( - rrtopUiState.screenUiState as MainScreenUiState, - modifier = Modifier.padding(bottom = 1), - ) - RrtopUiState.Screen.Cmd -> CmdScreen( - rrtopUiState.screenUiState as CmdScreenUiState, - modifier = Modifier.padding(bottom = 1), - ) - RrtopUiState.Screen.Stat -> StatScreen( - rrtopUiState.screenUiState as StatScreenUiState, - modifier = Modifier.padding(bottom = 1), - ) - RrtopUiState.Screen.Slow -> SlowScreen( - rrtopUiState.screenUiState as SlowScreenUiState, - modifier = Modifier.padding(bottom = 1), - ) - RrtopUiState.Screen.Raw -> RawScreen( - rrtopUiState.screenUiState as RawScreenUiState, - modifier = Modifier.padding(bottom = 1), + CompositionLocalProvider(LocalRrtopColorsPalette provides colorsPalette) { + Box( + modifier = Modifier + .width(terminal.size.width) + .height(terminal.size.height - 1) // subtraction of one is necessary, because there is a line with a cursor at the bottom, which moves up all the content + .background(LocalRrtopColorsPalette.current.mainBg), + ) { + when (rrtopUiState.currentScreen) { + RrtopUiState.Screen.Main -> MainScreen( + rrtopUiState.screenUiState as MainScreenUiState, + modifier = Modifier.padding(bottom = 1), + ) + RrtopUiState.Screen.Cmd -> CmdScreen( + rrtopUiState.screenUiState as CmdScreenUiState, + modifier = Modifier.padding(bottom = 1), + ) + RrtopUiState.Screen.Stat -> StatScreen( + rrtopUiState.screenUiState as StatScreenUiState, + modifier = Modifier.padding(bottom = 1), + ) + RrtopUiState.Screen.Slow -> SlowScreen( + rrtopUiState.screenUiState as SlowScreenUiState, + modifier = Modifier.padding(bottom = 1), + ) + RrtopUiState.Screen.Raw -> RawScreen( + rrtopUiState.screenUiState as RawScreenUiState, + modifier = Modifier.padding(bottom = 1), + ) + } + BottomStatusBar( + currentScreen = rrtopUiState.currentScreen, + commonInfo = rrtopUiState.commonInfo, + modifier = Modifier.fillMaxWidth() + .height(1) + .padding(horizontal = 1) + .align(Alignment.BottomCenter), ) } - BottomStatusBar( - currentScreen = rrtopUiState.currentScreen, - commonInfo = rrtopUiState.commonInfo, - modifier = Modifier.fillMaxWidth() - .height(1) - .padding(horizontal = 1) - .align(Alignment.BottomCenter), - ) } LaunchedEffect(Unit) { @@ -94,7 +98,7 @@ private fun BottomStatusBar( commonInfo: String, modifier: Modifier = Modifier, ) { - Box(modifier = modifier) { + Box(modifier = modifier.background(LocalRrtopColorsPalette.current.menuBg)) { Text( buildAnnotatedString { RrtopUiState.Screen.entries.forEachIndexed { index, screen -> @@ -105,19 +109,26 @@ private fun BottomStatusBar( RrtopUiState.Screen.Slow -> "Slow" RrtopUiState.Screen.Raw -> "Raw" } - withStyle(SpanStyle(if (screen == currentScreen) Color.BrightWhite else Color.BrightBlack)) { + if (screen == currentScreen) { + withStyle(SpanStyle(LocalRrtopColorsPalette.current.menuHighlightFg)) { + append(screenName) + } + } else { append(screenName) } if (index < RrtopUiState.Screen.entries.lastIndex) { - append(" | ") + withStyle(SpanStyle(LocalRrtopColorsPalette.current.menuDividerFg)) { + append(" | ") + } } } }, modifier = Modifier.align(Alignment.CenterStart), + color = LocalRrtopColorsPalette.current.menuFg, ) Text( commonInfo, - color = Color.BrightBlack, + color = LocalRrtopColorsPalette.current.statusBarFg, modifier = Modifier.align(Alignment.CenterEnd), ) } diff --git a/samples/rrtop/src/main/kotlin/example/RrtopColorsPalette.kt b/samples/rrtop/src/main/kotlin/example/RrtopColorsPalette.kt new file mode 100644 index 000000000..1de7ec7eb --- /dev/null +++ b/samples/rrtop/src/main/kotlin/example/RrtopColorsPalette.kt @@ -0,0 +1,84 @@ +package example + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.ProvidableCompositionLocal +import androidx.compose.runtime.staticCompositionLocalOf +import com.jakewharton.mosaic.ui.Color + +val LocalRrtopColorsPalette: ProvidableCompositionLocal = + staticCompositionLocalOf { throw IllegalStateException("No colors palette") } + +@Immutable +data class RrtopColorsPalette( + val mainBg: Color, + val menuBg: Color, + val menuFg: Color, + val menuDividerFg: Color, + val menuHighlightBg: Color, + val menuHighlightFg: Color, + val statusBarFg: Color, + val memoryTitleFg: Color, + val memoryBorderFg: Color, + val memoryMaxMemoryTextFg: Color, + val memoryUsedMemoryTextFg: Color, + val memoryUsedMemorySparklineFg: Color, + val memoryUsedMemorySparklineBaselineFg: Color, + val memoryFragRatioTextFg: Color, + val memoryRssMemoryTextFg: Color, + val memoryRssMemorySparklineFg: Color, + val memoryRssMemorySparklineBaselineFg: Color, + val cpuTitleFg: Color, + val cpuBorderFg: Color, + val cpuChartLineFg: Color, + val cpuChartAxisFg: Color, + val cpuSysCpuText1Fg: Color, + val cpuSysCpuText2Fg: Color, + val cpuSysCpuDatasetFg: Color, + val cpuUserCpuText1Fg: Color, + val cpuUserCpuText2Fg: Color, + val cpuUserCpuDatasetFg: Color, + val throughputTitleFg: Color, + val throughputBorderFg: Color, + val throughputTotalCommandsTextFg: Color, + val throughputOpsTextFg: Color, + val throughputSparklineFg: Color, + val throughputSparklineBaselineFg: Color, + val networkTitleFg: Color, + val networkBorderFg: Color, + val networkRxTotalTextFg: Color, + val networkRxSTextFg: Color, + val networkRxSparklineFg: Color, + val networkRxSparklineBaselineFg: Color, + val networkTxTotalTextFg: Color, + val networkTxSTextFg: Color, + val networkTxSparklineFg: Color, + val networkTxSparklineBaselineFg: Color, + val statTitleFg: Color, + val statBorderFg: Color, + val statTableHeaderFg: Color, + val statTableRowGaugeFg: Color, + val statTableRowGaugeBg: Color, + val statTableRowTop1Fg: Color, + val statTableRowTop2Fg: Color, + val statTableRowHighlightBg: Color, + val callsTitleFg: Color, + val callsBorderFg: Color, + val callsTableHeaderFg: Color, + val callsTableRowGaugeFg: Color, + val callsTableRowGaugeBg: Color, + val callsTableRowTop1Fg: Color, + val callsTableRowTop2Fg: Color, + val callsTableRowHighlightBg: Color, + val rawTitleFg: Color, + val rawBorderFg: Color, + val rawTableHeaderFg: Color, + val rawTableRowTop1Fg: Color, + val rawTableRowTop2Fg: Color, + val rawTableRowHighlightBg: Color, + val slowTitleFg: Color, + val slowBorderFg: Color, + val slowTableHeaderFg: Color, + val slowTableRowTop1Fg: Color, + val slowTableRowTop2Fg: Color, + val slowTableRowHighlightBg: Color, +) diff --git a/samples/rrtop/src/main/kotlin/example/common/BorderedTitledBox.kt b/samples/rrtop/src/main/kotlin/example/common/BorderedTitledBox.kt index d18afd16d..06bc2c8b2 100644 --- a/samples/rrtop/src/main/kotlin/example/common/BorderedTitledBox.kt +++ b/samples/rrtop/src/main/kotlin/example/common/BorderedTitledBox.kt @@ -4,19 +4,35 @@ import androidx.compose.runtime.Composable import com.jakewharton.mosaic.layout.offset import com.jakewharton.mosaic.layout.padding import com.jakewharton.mosaic.modifier.Modifier +import com.jakewharton.mosaic.text.SpanStyle +import com.jakewharton.mosaic.text.buildAnnotatedString +import com.jakewharton.mosaic.text.withStyle import com.jakewharton.mosaic.ui.Alignment import com.jakewharton.mosaic.ui.Box import com.jakewharton.mosaic.ui.BoxScope +import com.jakewharton.mosaic.ui.Color import com.jakewharton.mosaic.ui.Text @Composable fun BorderedTitledBox( title: String, + titleColor: Color, + borderColor: Color, modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit, ) { - Box(modifier = modifier.border().padding(horizontal = 1)) { - Text("┐ $title ┌", modifier = Modifier.align(Alignment.TopStart).offset(x = -1, y = -1)) + Box(modifier = modifier.border(color = borderColor).padding(horizontal = 1)) { + Text( + buildAnnotatedString { + append("┐ ") + withStyle(SpanStyle(titleColor)) { + append(title) + } + append(" ┌") + }, + modifier = Modifier.align(Alignment.TopStart).offset(x = -1, y = -1), + color = borderColor, + ) content() } } diff --git a/samples/rrtop/src/main/kotlin/example/common/Table.kt b/samples/rrtop/src/main/kotlin/example/common/Table.kt index e04a555a0..d137b79bf 100644 --- a/samples/rrtop/src/main/kotlin/example/common/Table.kt +++ b/samples/rrtop/src/main/kotlin/example/common/Table.kt @@ -18,6 +18,7 @@ data class TableData(val items: List) @Immutable data class TableConfig( + val titleColor: Color, val columnConfigs: List>, ) { @@ -29,8 +30,7 @@ data class TableConfig( data class StringColumnConfig( val title: String, val stringFromItem: (T) -> String, - val titleColor: Color = Color.Cyan, - val valueColor: Color = Color.White, + val valueColor: Color, val valueAlignment: ColumnAligment = ColumnAligment.START, override val weight: Int = 1, ) : ColumnConfig @@ -51,18 +51,18 @@ data class TableConfig( } @Composable -fun Table(tableData: TableData, config: TableConfig, modifier: Modifier = Modifier) { +fun Table(tableData: TableData, tableConfig: TableConfig, modifier: Modifier = Modifier) { Box( modifier = modifier .drawBehind { - val weights = config.columnConfigs.sumOf { it.weight } - val widthSinglePart = (width - config.columnConfigs.size) / weights - val widths = config.columnConfigs.map { it.weight * widthSinglePart } + val weights = tableConfig.columnConfigs.sumOf { it.weight } + val widthSinglePart = (width - tableConfig.columnConfigs.size) / weights + val widths = tableConfig.columnConfigs.map { it.weight * widthSinglePart } val lastRange = tableData.items.takeLast(height - 1).asReversed() var column = 0 - config.columnConfigs.forEachIndexed { columnIndex, columnConfig -> + tableConfig.columnConfigs.forEachIndexed { columnIndex, columnConfig -> val columnWidth = widths[columnIndex] if (columnConfig is TableConfig.ColumnConfig.StringColumnConfig) { val title = if (columnConfig.title.length < columnWidth) { @@ -74,7 +74,7 @@ fun Table(tableData: TableData, config: TableConfig, modifier: Modifie row = 0, column = column, string = title, - foreground = columnConfig.titleColor, + foreground = tableConfig.titleColor, ) } diff --git a/samples/rrtop/src/main/kotlin/example/palletes/BlackBirdColorsPalette.kt b/samples/rrtop/src/main/kotlin/example/palletes/BlackBirdColorsPalette.kt new file mode 100644 index 000000000..1468582f3 --- /dev/null +++ b/samples/rrtop/src/main/kotlin/example/palletes/BlackBirdColorsPalette.kt @@ -0,0 +1,87 @@ +package example.palletes + +import com.jakewharton.mosaic.ui.Color +import example.RrtopColorsPalette + +private val White = Color(253, 247, 205) +private val Cyan = Color(0, 236, 216) +private val Red = Color(233, 39, 65) +private val Green = Color(62, 200, 64) +private val Blue = Color(65, 143, 221) +private val Orange = Color(255, 153, 0) +private val Black1 = Color(0, 0, 0) +private val Black2 = Color(52, 60, 80) + +val BlackBirdColorsPalette = RrtopColorsPalette( + mainBg = Black1, + menuBg = Black1, + menuFg = Black2, + menuDividerFg = Black2, + menuHighlightBg = Black1, + menuHighlightFg = Orange, + statusBarFg = Blue, + memoryTitleFg = White, + memoryBorderFg = Black2, + memoryMaxMemoryTextFg = Blue, + memoryUsedMemoryTextFg = Blue, + memoryUsedMemorySparklineFg = Blue, + memoryUsedMemorySparklineBaselineFg = Black2, + memoryFragRatioTextFg = Green, + memoryRssMemoryTextFg = Green, + memoryRssMemorySparklineFg = Green, + memoryRssMemorySparklineBaselineFg = Black2, + cpuTitleFg = White, + cpuBorderFg = Black2, + cpuChartLineFg = Black2, + cpuChartAxisFg = White, + cpuSysCpuText1Fg = White, + cpuSysCpuText2Fg = Red, + cpuSysCpuDatasetFg = Red, + cpuUserCpuText1Fg = White, + cpuUserCpuText2Fg = Green, + cpuUserCpuDatasetFg = Green, + throughputTitleFg = White, + throughputBorderFg = Black2, + throughputTotalCommandsTextFg = Blue, + throughputOpsTextFg = Blue, + throughputSparklineFg = Blue, + throughputSparklineBaselineFg = Black2, + networkTitleFg = White, + networkBorderFg = Black2, + networkRxTotalTextFg = Orange, + networkRxSTextFg = Orange, + networkRxSparklineFg = Orange, + networkRxSparklineBaselineFg = Black2, + networkTxTotalTextFg = Blue, + networkTxSTextFg = Blue, + networkTxSparklineFg = Blue, + networkTxSparklineBaselineFg = Black2, + statTitleFg = White, + statBorderFg = Black2, + statTableHeaderFg = Cyan, + statTableRowGaugeFg = Blue, + statTableRowGaugeBg = Black2, + statTableRowTop1Fg = White, + statTableRowTop2Fg = Blue, + statTableRowHighlightBg = Orange, + callsTitleFg = White, + callsBorderFg = Black2, + callsTableHeaderFg = Cyan, + callsTableRowGaugeFg = Blue, + callsTableRowGaugeBg = Black2, + callsTableRowTop1Fg = White, + callsTableRowTop2Fg = Blue, + callsTableRowHighlightBg = Orange, + rawTitleFg = White, + rawBorderFg = Black2, + rawTableHeaderFg = Cyan, + rawTableRowTop1Fg = White, + rawTableRowTop2Fg = Blue, + rawTableRowHighlightBg = Orange, + slowTitleFg = White, + slowBorderFg = Black2, + slowTableHeaderFg = Cyan, + slowTableRowTop1Fg = White, + slowTableRowTop2Fg = Blue, + slowTableRowHighlightBg = Orange, +) diff --git a/samples/rrtop/src/main/kotlin/example/palletes/DefaultColorsPalette.kt b/samples/rrtop/src/main/kotlin/example/palletes/DefaultColorsPalette.kt new file mode 100644 index 000000000..fdc4bde90 --- /dev/null +++ b/samples/rrtop/src/main/kotlin/example/palletes/DefaultColorsPalette.kt @@ -0,0 +1,87 @@ +package example.palletes + +import com.jakewharton.mosaic.ui.Color +import example.RrtopColorsPalette + +private val Black = Color(0, 0, 0) +private val White = Color(211, 215, 207) +private val DarkGray = Color(104, 106, 113) +private val Blue = Color(114, 159, 207) +private val Green = Color(78, 154, 6) +private val Red = Color(204, 0, 0) +private val Gray = Color(128, 128, 128) +private val Cyan = Color(6, 152, 154) + +val DefaultColorsPalette = RrtopColorsPalette( + mainBg = Black, + menuBg = Black, + menuFg = DarkGray, + menuDividerFg = DarkGray, + menuHighlightBg = Black, + menuHighlightFg = Blue, + statusBarFg = DarkGray, + memoryTitleFg = White, + memoryBorderFg = DarkGray, + memoryMaxMemoryTextFg = Blue, + memoryUsedMemoryTextFg = Blue, + memoryUsedMemorySparklineFg = Blue, + memoryUsedMemorySparklineBaselineFg = DarkGray, + memoryFragRatioTextFg = Green, + memoryRssMemoryTextFg = Green, + memoryRssMemorySparklineFg = Green, + memoryRssMemorySparklineBaselineFg = DarkGray, + cpuTitleFg = White, + cpuBorderFg = DarkGray, + cpuChartLineFg = DarkGray, + cpuChartAxisFg = DarkGray, + cpuSysCpuText1Fg = White, + cpuSysCpuText2Fg = Red, + cpuSysCpuDatasetFg = Red, + cpuUserCpuText1Fg = White, + cpuUserCpuText2Fg = Green, + cpuUserCpuDatasetFg = Green, + throughputTitleFg = White, + throughputBorderFg = DarkGray, + throughputTotalCommandsTextFg = Blue, + throughputOpsTextFg = Blue, + throughputSparklineFg = Blue, + throughputSparklineBaselineFg = DarkGray, + networkTitleFg = White, + networkBorderFg = DarkGray, + networkRxTotalTextFg = Red, + networkRxSTextFg = Red, + networkRxSparklineFg = Red, + networkRxSparklineBaselineFg = DarkGray, + networkTxTotalTextFg = Blue, + networkTxSTextFg = Blue, + networkTxSparklineFg = Blue, + networkTxSparklineBaselineFg = DarkGray, + statTitleFg = White, + statBorderFg = DarkGray, + statTableHeaderFg = Cyan, + statTableRowGaugeFg = Blue, + statTableRowGaugeBg = Gray, + statTableRowTop1Fg = White, + statTableRowTop2Fg = Blue, + statTableRowHighlightBg = DarkGray, + callsTitleFg = White, + callsBorderFg = DarkGray, + callsTableHeaderFg = Cyan, + callsTableRowGaugeFg = Blue, + callsTableRowGaugeBg = Gray, + callsTableRowTop1Fg = White, + callsTableRowTop2Fg = Blue, + callsTableRowHighlightBg = DarkGray, + rawTitleFg = White, + rawBorderFg = DarkGray, + rawTableHeaderFg = Cyan, + rawTableRowTop1Fg = White, + rawTableRowTop2Fg = Blue, + rawTableRowHighlightBg = DarkGray, + slowTitleFg = White, + slowBorderFg = DarkGray, + slowTableHeaderFg = Cyan, + slowTableRowTop1Fg = White, + slowTableRowTop2Fg = Blue, + slowTableRowHighlightBg = DarkGray, +) diff --git a/samples/rrtop/src/main/kotlin/example/palletes/DraculaColorsPalette.kt b/samples/rrtop/src/main/kotlin/example/palletes/DraculaColorsPalette.kt new file mode 100644 index 000000000..521f7edcc --- /dev/null +++ b/samples/rrtop/src/main/kotlin/example/palletes/DraculaColorsPalette.kt @@ -0,0 +1,87 @@ +package example.palletes + +import com.jakewharton.mosaic.ui.Color +import example.RrtopColorsPalette + +private val White = Color(248, 248, 242) +private val Cyan = Color(139, 233, 253) +private val Red = Color(255, 85, 85) +private val Green = Color(80, 250, 123) +private val Blue = Color(98, 114, 164) +private val Orange = Color(255, 184, 108) +private val Black1 = Color(40, 42, 54) +private val Black2 = Color(68, 71, 90) + +val DraculaColorsPalette = RrtopColorsPalette( + mainBg = Black1, + menuBg = Black1, + menuFg = White, + menuDividerFg = Black2, + menuHighlightBg = Black1, + menuHighlightFg = Orange, + statusBarFg = Blue, + memoryTitleFg = White, + memoryBorderFg = Black2, + memoryMaxMemoryTextFg = Blue, + memoryUsedMemoryTextFg = Blue, + memoryUsedMemorySparklineFg = Blue, + memoryUsedMemorySparklineBaselineFg = Black2, + memoryFragRatioTextFg = Green, + memoryRssMemoryTextFg = Green, + memoryRssMemorySparklineFg = Green, + memoryRssMemorySparklineBaselineFg = Black2, + cpuTitleFg = White, + cpuBorderFg = Black2, + cpuChartLineFg = Black2, + cpuChartAxisFg = White, + cpuSysCpuText1Fg = White, + cpuSysCpuText2Fg = Red, + cpuSysCpuDatasetFg = Red, + cpuUserCpuText1Fg = White, + cpuUserCpuText2Fg = Green, + cpuUserCpuDatasetFg = Green, + throughputTitleFg = White, + throughputBorderFg = Black2, + throughputTotalCommandsTextFg = Blue, + throughputOpsTextFg = Blue, + throughputSparklineFg = Blue, + throughputSparklineBaselineFg = Black2, + networkTitleFg = White, + networkBorderFg = Black2, + networkRxTotalTextFg = Orange, + networkRxSTextFg = Orange, + networkRxSparklineFg = Orange, + networkRxSparklineBaselineFg = Black2, + networkTxTotalTextFg = Blue, + networkTxSTextFg = Blue, + networkTxSparklineFg = Blue, + networkTxSparklineBaselineFg = Black2, + statTitleFg = White, + statBorderFg = Black2, + statTableHeaderFg = Cyan, + statTableRowGaugeFg = Blue, + statTableRowGaugeBg = Black2, + statTableRowTop1Fg = White, + statTableRowTop2Fg = Blue, + statTableRowHighlightBg = Orange, + callsTitleFg = White, + callsBorderFg = Black2, + callsTableHeaderFg = Cyan, + callsTableRowGaugeFg = Blue, + callsTableRowGaugeBg = Black2, + callsTableRowTop1Fg = White, + callsTableRowTop2Fg = Blue, + callsTableRowHighlightBg = Orange, + rawTitleFg = White, + rawBorderFg = Black2, + rawTableHeaderFg = Cyan, + rawTableRowTop1Fg = White, + rawTableRowTop2Fg = Blue, + rawTableRowHighlightBg = Orange, + slowTitleFg = White, + slowBorderFg = Black2, + slowTableHeaderFg = Cyan, + slowTableRowTop1Fg = White, + slowTableRowTop2Fg = Blue, + slowTableRowHighlightBg = Orange, +) diff --git a/samples/rrtop/src/main/kotlin/example/palletes/NordColorsPalette.kt b/samples/rrtop/src/main/kotlin/example/palletes/NordColorsPalette.kt new file mode 100644 index 000000000..53f6e6bfa --- /dev/null +++ b/samples/rrtop/src/main/kotlin/example/palletes/NordColorsPalette.kt @@ -0,0 +1,88 @@ +package example.palletes + +import com.jakewharton.mosaic.ui.Color +import example.RrtopColorsPalette + +private val Nord0 = Color(46, 52, 64) +private val Nord1 = Color(59, 66, 82) +private val Nord2 = Color(67, 76, 94) +private val Nord3 = Color(76, 86, 106) +private val Nord6 = Color(236, 239, 244) +private val Nord7 = Color(143, 188, 187) +private val Nord9 = Color(129, 161, 193) +private val Nord11 = Color(191, 97, 106) +private val Nord14 = Color(163, 190, 140) + +val NordColorsPalette = RrtopColorsPalette( + mainBg = Nord0, + menuBg = Nord0, + menuFg = Nord3, + menuDividerFg = Nord3, + menuHighlightBg = Nord0, + menuHighlightFg = Nord9, + statusBarFg = Nord3, + memoryTitleFg = Nord7, + memoryBorderFg = Nord3, + memoryMaxMemoryTextFg = Nord11, + memoryUsedMemoryTextFg = Nord9, + memoryUsedMemorySparklineFg = Nord9, + memoryUsedMemorySparklineBaselineFg = Nord3, + memoryFragRatioTextFg = Nord14, + memoryRssMemoryTextFg = Nord14, + memoryRssMemorySparklineFg = Nord14, + memoryRssMemorySparklineBaselineFg = Nord3, + cpuTitleFg = Nord7, + cpuBorderFg = Nord3, + cpuChartLineFg = Nord3, + cpuChartAxisFg = Nord3, + cpuSysCpuText1Fg = Nord3, + cpuSysCpuText2Fg = Nord3, + cpuSysCpuDatasetFg = Nord11, + cpuUserCpuText1Fg = Nord3, + cpuUserCpuText2Fg = Nord3, + cpuUserCpuDatasetFg = Nord9, + throughputTitleFg = Nord7, + throughputBorderFg = Nord3, + throughputTotalCommandsTextFg = Nord9, + throughputOpsTextFg = Nord9, + throughputSparklineFg = Nord9, + throughputSparklineBaselineFg = Nord3, + networkTitleFg = Nord7, + networkBorderFg = Nord3, + networkRxTotalTextFg = Nord9, + networkRxSTextFg = Nord9, + networkRxSparklineFg = Nord9, + networkRxSparklineBaselineFg = Nord3, + networkTxTotalTextFg = Nord14, + networkTxSTextFg = Nord14, + networkTxSparklineFg = Nord14, + networkTxSparklineBaselineFg = Nord3, + statTitleFg = Nord7, + statBorderFg = Nord3, + statTableHeaderFg = Nord7, + statTableRowGaugeFg = Nord9, + statTableRowGaugeBg = Nord1, + statTableRowTop1Fg = Nord6, + statTableRowTop2Fg = Nord9, + statTableRowHighlightBg = Nord2, + callsTitleFg = Nord7, + callsBorderFg = Nord3, + callsTableHeaderFg = Nord7, + callsTableRowGaugeFg = Nord9, + callsTableRowGaugeBg = Nord1, + callsTableRowTop1Fg = Nord6, + callsTableRowTop2Fg = Nord9, + callsTableRowHighlightBg = Nord2, + rawTitleFg = Nord7, + rawBorderFg = Nord3, + rawTableHeaderFg = Nord7, + rawTableRowTop1Fg = Nord6, + rawTableRowTop2Fg = Nord9, + rawTableRowHighlightBg = Nord2, + slowTitleFg = Nord7, + slowBorderFg = Nord3, + slowTableHeaderFg = Nord7, + slowTableRowTop1Fg = Nord6, + slowTableRowTop2Fg = Nord9, + slowTableRowHighlightBg = Nord2, +) diff --git a/samples/rrtop/src/main/kotlin/example/palletes/OneDarkColorsPalette.kt b/samples/rrtop/src/main/kotlin/example/palletes/OneDarkColorsPalette.kt new file mode 100644 index 000000000..7a263618a --- /dev/null +++ b/samples/rrtop/src/main/kotlin/example/palletes/OneDarkColorsPalette.kt @@ -0,0 +1,87 @@ +package example.palletes + +import com.jakewharton.mosaic.ui.Color +import example.RrtopColorsPalette + +private val White = Color(171, 178, 191) +private val Cyan = Color(86, 182, 194) +private val Red = Color(24, 108, 117) +private val Green = Color(152, 195, 121) +private val Blue = Color(97, 175, 239) +private val Black1 = Color(49, 53, 63) +private val Black2 = Color(92, 99, 112) +private val Purple = Color(198, 120, 221) + +val OneDarkColorsPalette = RrtopColorsPalette( + mainBg = Black1, + menuBg = Black1, + menuFg = White, + menuDividerFg = Black2, + menuHighlightBg = Black1, + menuHighlightFg = Purple, + statusBarFg = Blue, + memoryTitleFg = White, + memoryBorderFg = Black2, + memoryMaxMemoryTextFg = Blue, + memoryUsedMemoryTextFg = Blue, + memoryUsedMemorySparklineFg = Blue, + memoryUsedMemorySparklineBaselineFg = Black2, + memoryFragRatioTextFg = Green, + memoryRssMemoryTextFg = Green, + memoryRssMemorySparklineFg = Green, + memoryRssMemorySparklineBaselineFg = Black2, + cpuTitleFg = White, + cpuBorderFg = Black2, + cpuChartLineFg = Black2, + cpuChartAxisFg = Black2, + cpuSysCpuText1Fg = White, + cpuSysCpuText2Fg = Red, + cpuSysCpuDatasetFg = Red, + cpuUserCpuText1Fg = White, + cpuUserCpuText2Fg = Green, + cpuUserCpuDatasetFg = Green, + throughputTitleFg = White, + throughputBorderFg = Black2, + throughputTotalCommandsTextFg = Blue, + throughputOpsTextFg = Blue, + throughputSparklineFg = Blue, + throughputSparklineBaselineFg = Black2, + networkTitleFg = White, + networkBorderFg = Black2, + networkRxTotalTextFg = Red, + networkRxSTextFg = Red, + networkRxSparklineFg = Red, + networkRxSparklineBaselineFg = Black2, + networkTxTotalTextFg = Blue, + networkTxSTextFg = Blue, + networkTxSparklineFg = Blue, + networkTxSparklineBaselineFg = Black2, + statTitleFg = White, + statBorderFg = Black2, + statTableHeaderFg = Cyan, + statTableRowGaugeFg = Blue, + statTableRowGaugeBg = Black2, + statTableRowTop1Fg = White, + statTableRowTop2Fg = Blue, + statTableRowHighlightBg = Purple, + callsTitleFg = White, + callsBorderFg = Black2, + callsTableHeaderFg = Cyan, + callsTableRowGaugeFg = Blue, + callsTableRowGaugeBg = Black2, + callsTableRowTop1Fg = White, + callsTableRowTop2Fg = Blue, + callsTableRowHighlightBg = Purple, + rawTitleFg = White, + rawBorderFg = Black2, + rawTableHeaderFg = Cyan, + rawTableRowTop1Fg = White, + rawTableRowTop2Fg = Blue, + rawTableRowHighlightBg = Purple, + slowTitleFg = White, + slowBorderFg = Black2, + slowTableHeaderFg = Cyan, + slowTableRowTop1Fg = White, + slowTableRowTop2Fg = Blue, + slowTableRowHighlightBg = Purple, +) diff --git a/samples/rrtop/src/main/kotlin/example/palletes/SolarizedDarkColorsPalette.kt b/samples/rrtop/src/main/kotlin/example/palletes/SolarizedDarkColorsPalette.kt new file mode 100644 index 000000000..93993a643 --- /dev/null +++ b/samples/rrtop/src/main/kotlin/example/palletes/SolarizedDarkColorsPalette.kt @@ -0,0 +1,87 @@ +package example.palletes + +import com.jakewharton.mosaic.ui.Color +import example.RrtopColorsPalette + +private val White = Color(248, 248, 242) +private val Cyan = Color(42, 161, 152) +private val Red = Color(211, 1, 2) +private val Green = Color(133, 153, 0) +private val Blue = Color(38, 139, 210) +private val Orange = Color(203, 75, 22) +private val Black1 = Color(0, 43, 54) +private val Black2 = Color(7, 54, 66) + +val SolarizedDarkColorsPalette = RrtopColorsPalette( + mainBg = Black1, + menuBg = Black1, + menuFg = White, + menuDividerFg = Black2, + menuHighlightBg = Black1, + menuHighlightFg = Orange, + statusBarFg = Blue, + memoryTitleFg = White, + memoryBorderFg = Black2, + memoryMaxMemoryTextFg = Blue, + memoryUsedMemoryTextFg = Blue, + memoryUsedMemorySparklineFg = Blue, + memoryUsedMemorySparklineBaselineFg = Black2, + memoryFragRatioTextFg = Green, + memoryRssMemoryTextFg = Green, + memoryRssMemorySparklineFg = Green, + memoryRssMemorySparklineBaselineFg = Black2, + cpuTitleFg = White, + cpuBorderFg = Black2, + cpuChartLineFg = Black2, + cpuChartAxisFg = White, + cpuSysCpuText1Fg = White, + cpuSysCpuText2Fg = Red, + cpuSysCpuDatasetFg = Red, + cpuUserCpuText1Fg = White, + cpuUserCpuText2Fg = Green, + cpuUserCpuDatasetFg = Green, + throughputTitleFg = White, + throughputBorderFg = Black2, + throughputTotalCommandsTextFg = Blue, + throughputOpsTextFg = Blue, + throughputSparklineFg = Blue, + throughputSparklineBaselineFg = Black2, + networkTitleFg = White, + networkBorderFg = Black2, + networkRxTotalTextFg = Orange, + networkRxSTextFg = Orange, + networkRxSparklineFg = Orange, + networkRxSparklineBaselineFg = Black2, + networkTxTotalTextFg = Blue, + networkTxSTextFg = Blue, + networkTxSparklineFg = Blue, + networkTxSparklineBaselineFg = Black2, + statTitleFg = White, + statBorderFg = Black2, + statTableHeaderFg = Cyan, + statTableRowGaugeFg = Blue, + statTableRowGaugeBg = Black2, + statTableRowTop1Fg = White, + statTableRowTop2Fg = Blue, + statTableRowHighlightBg = Orange, + callsTitleFg = White, + callsBorderFg = Black2, + callsTableHeaderFg = Cyan, + callsTableRowGaugeFg = Blue, + callsTableRowGaugeBg = Black2, + callsTableRowTop1Fg = White, + callsTableRowTop2Fg = Blue, + callsTableRowHighlightBg = Orange, + rawTitleFg = White, + rawBorderFg = Black2, + rawTableHeaderFg = Cyan, + rawTableRowTop1Fg = White, + rawTableRowTop2Fg = Blue, + rawTableRowHighlightBg = Orange, + slowTitleFg = White, + slowBorderFg = Black2, + slowTableHeaderFg = Cyan, + slowTableRowTop1Fg = White, + slowTableRowTop2Fg = Blue, + slowTableRowHighlightBg = Orange, +) diff --git a/samples/rrtop/src/main/kotlin/example/rrtop.kt b/samples/rrtop/src/main/kotlin/example/rrtop.kt index dbc5c1bc7..4c510b1fe 100644 --- a/samples/rrtop/src/main/kotlin/example/rrtop.kt +++ b/samples/rrtop/src/main/kotlin/example/rrtop.kt @@ -1,15 +1,38 @@ package example import com.jakewharton.mosaic.runMosaicBlocking +import example.palletes.BlackBirdColorsPalette +import example.palletes.DefaultColorsPalette +import example.palletes.DraculaColorsPalette +import example.palletes.NordColorsPalette +import example.palletes.OneDarkColorsPalette +import example.palletes.SolarizedDarkColorsPalette import kotlinx.coroutines.suspendCancellableCoroutine -fun main() = runMosaicBlocking { +fun main(args: Array) = runMosaicBlocking { + val rrtopColorsPalette = parseArgsForColorsPalette(args) val rrtopViewModel = RrtopViewModel(this) setContent { - RrtopApp(rrtopViewModel) + RrtopApp(rrtopViewModel, rrtopColorsPalette) } // Run forever! suspendCancellableCoroutine {} } + +private fun parseArgsForColorsPalette(args: Array): RrtopColorsPalette { + val keyIndex = args.indexOf("-c") + if (keyIndex < 0 || keyIndex >= args.lastIndex) { + return DefaultColorsPalette + } + return when (args[keyIndex + 1]) { + "default" -> DefaultColorsPalette + "blackbird" -> BlackBirdColorsPalette + "dracula" -> DraculaColorsPalette + "nord" -> NordColorsPalette + "one-dark" -> OneDarkColorsPalette + "solarized-dark" -> SolarizedDarkColorsPalette + else -> DefaultColorsPalette + } +} diff --git a/samples/rrtop/src/main/kotlin/example/screens/CmdScreen.kt b/samples/rrtop/src/main/kotlin/example/screens/CmdScreen.kt index bd3897abf..9b1271635 100644 --- a/samples/rrtop/src/main/kotlin/example/screens/CmdScreen.kt +++ b/samples/rrtop/src/main/kotlin/example/screens/CmdScreen.kt @@ -2,8 +2,8 @@ package example.screens import androidx.compose.runtime.Composable import com.jakewharton.mosaic.modifier.Modifier -import com.jakewharton.mosaic.ui.Color import example.CmdScreenUiState +import example.LocalRrtopColorsPalette import example.common.BorderedTitledBox import example.common.Table import example.common.TableConfig @@ -11,64 +11,71 @@ import example.common.TableData @Composable fun CmdScreen(uiState: CmdScreenUiState, modifier: Modifier = Modifier) { - BorderedTitledBox(title = "by calls", modifier = modifier) { + BorderedTitledBox( + title = "by calls", + titleColor = LocalRrtopColorsPalette.current.callsTitleFg, + borderColor = LocalRrtopColorsPalette.current.callsBorderFg, + modifier = modifier, + ) { Table( TableData(uiState.items), TableConfig( - listOf( + titleColor = LocalRrtopColorsPalette.current.callsTableHeaderFg, + columnConfigs = listOf( TableConfig.ColumnConfig.StringColumnConfig( title = "command", stringFromItem = { it.command }, + valueColor = LocalRrtopColorsPalette.current.callsTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "calls", stringFromItem = { it.calls }, - valueColor = Color.Blue, + valueColor = LocalRrtopColorsPalette.current.callsTableRowTop2Fg, valueAlignment = TableConfig.ColumnConfig.ColumnAligment.END, ), TableConfig.ColumnConfig.StringColumnConfig( title = "", stringFromItem = { it.callsPercentFormatted }, - valueColor = Color.Blue, + valueColor = LocalRrtopColorsPalette.current.callsTableRowTop2Fg, valueAlignment = TableConfig.ColumnConfig.ColumnAligment.END, ), TableConfig.ColumnConfig.ProgressColumnConfig( - filledColor = Color.Blue, - emptyColor = Color.BrightBlack, + filledColor = LocalRrtopColorsPalette.current.callsTableRowGaugeFg, + emptyColor = LocalRrtopColorsPalette.current.callsTableRowGaugeBg, progressFromItem = { it.callsPercent / 100.0f }, ), TableConfig.ColumnConfig.StringColumnConfig( title = "usec", stringFromItem = { it.usec }, - valueColor = Color.Blue, + valueColor = LocalRrtopColorsPalette.current.callsTableRowTop2Fg, valueAlignment = TableConfig.ColumnConfig.ColumnAligment.END, ), TableConfig.ColumnConfig.StringColumnConfig( title = "", stringFromItem = { it.usecPercentFormatted }, - valueColor = Color.Blue, + valueColor = LocalRrtopColorsPalette.current.callsTableRowTop2Fg, valueAlignment = TableConfig.ColumnConfig.ColumnAligment.END, ), TableConfig.ColumnConfig.ProgressColumnConfig( - filledColor = Color.Blue, - emptyColor = Color.BrightBlack, + filledColor = LocalRrtopColorsPalette.current.callsTableRowGaugeFg, + emptyColor = LocalRrtopColorsPalette.current.callsTableRowGaugeBg, progressFromItem = { it.usecPercent / 100.0f }, ), TableConfig.ColumnConfig.StringColumnConfig( title = "usec per call", stringFromItem = { it.usecPerCall }, - valueColor = Color.Blue, + valueColor = LocalRrtopColorsPalette.current.callsTableRowTop2Fg, valueAlignment = TableConfig.ColumnConfig.ColumnAligment.END, ), TableConfig.ColumnConfig.StringColumnConfig( title = "", stringFromItem = { it.usecPerCallPercentFormatted }, - valueColor = Color.Blue, + valueColor = LocalRrtopColorsPalette.current.callsTableRowTop2Fg, valueAlignment = TableConfig.ColumnConfig.ColumnAligment.END, ), TableConfig.ColumnConfig.ProgressColumnConfig( - filledColor = Color.Blue, - emptyColor = Color.BrightBlack, + filledColor = LocalRrtopColorsPalette.current.callsTableRowGaugeFg, + emptyColor = LocalRrtopColorsPalette.current.callsTableRowGaugeBg, progressFromItem = { it.usecPerCallPercent / 100.0f }, ), ), diff --git a/samples/rrtop/src/main/kotlin/example/screens/MainScreen.kt b/samples/rrtop/src/main/kotlin/example/screens/MainScreen.kt index cdc6d1670..15a95a956 100644 --- a/samples/rrtop/src/main/kotlin/example/screens/MainScreen.kt +++ b/samples/rrtop/src/main/kotlin/example/screens/MainScreen.kt @@ -20,6 +20,7 @@ import com.jakewharton.mosaic.ui.Column import com.jakewharton.mosaic.ui.Row import com.jakewharton.mosaic.ui.Spacer import com.jakewharton.mosaic.ui.Text +import example.LocalRrtopColorsPalette import example.MainScreenUiState import example.common.BorderedTitledBox import example.common.Table @@ -46,9 +47,15 @@ fun MainScreen(uiState: MainScreenUiState, modifier: Modifier = Modifier) { @Composable private fun CpuSection(uiState: MainScreenUiState, modifier: Modifier = Modifier) { - BorderedTitledBox(title = "cpu", modifier = modifier) { + BorderedTitledBox( + title = "cpu", + titleColor = LocalRrtopColorsPalette.current.cpuTitleFg, + borderColor = LocalRrtopColorsPalette.current.cpuBorderFg, + modifier = modifier, + ) { Row { val endOffsetForLabels = 7 + val chartLineForeground = LocalRrtopColorsPalette.current.cpuChartLineFg Column( modifier = Modifier .fillMaxWidth(0.6f) @@ -58,14 +65,15 @@ private fun CpuSection(uiState: MainScreenUiState, modifier: Modifier = Modifier row = height / 2, column = 0, string = "·".repeat(width - endOffsetForLabels), - foreground = Color.BrightBlack, + foreground = chartLineForeground, ) }, ) { LabeledDottedPlot( + labelColor = LocalRrtopColorsPalette.current.cpuChartAxisFg, plotInfo = PlotInfo( items = uiState.items, - color = Color.Red, + color = LocalRrtopColorsPalette.current.cpuSysCpuDatasetFg, numberFromItem = { it.sysCpuUtilization }, stringFromItem = { it.sysCpuUtilizationFormatted }, ), @@ -73,9 +81,10 @@ private fun CpuSection(uiState: MainScreenUiState, modifier: Modifier = Modifier modifier = Modifier.fillMaxWidth().fillMaxHeight(0.5f), ) LabeledDottedPlot( + labelColor = LocalRrtopColorsPalette.current.cpuChartAxisFg, plotInfo = PlotInfo( items = uiState.items, - color = Color.Green, + color = LocalRrtopColorsPalette.current.cpuUserCpuDatasetFg, numberFromItem = { it.userCpuUtilization }, stringFromItem = { it.userCpuUtilizationFormatted }, ), @@ -96,13 +105,21 @@ private fun CpuSection(uiState: MainScreenUiState, modifier: Modifier = Modifier @Composable private fun CpuThroughputSubsection(uiState: MainScreenUiState, modifier: Modifier = Modifier) { - BorderedTitledBox(title = "throughput", modifier = modifier) { + BorderedTitledBox( + title = "throughput", + titleColor = LocalRrtopColorsPalette.current.throughputTitleFg, + borderColor = LocalRrtopColorsPalette.current.throughputBorderFg, + modifier = modifier, + ) { TitledSolidPlot( firstTitle = "Total commands: ${uiState.items.lastOrNull()?.totalOperations ?: "0"}", + firstTitleColor = LocalRrtopColorsPalette.current.throughputTotalCommandsTextFg, secondTitle = " Op/s: ${uiState.items.lastOrNull()?.operationsPerSecondFormatted ?: "0"}", + secondTitleColor = LocalRrtopColorsPalette.current.throughputOpsTextFg, plotInfo = PlotInfo( items = uiState.items, - color = Color.Blue, + color = LocalRrtopColorsPalette.current.throughputSparklineFg, + baselineColor = LocalRrtopColorsPalette.current.throughputSparklineBaselineFg, numberFromItem = { it.operationsPerSecond }, stringFromItem = { it.operationsPerSecondFormatted }, ), @@ -119,19 +136,23 @@ private fun CpuLegendInfo( ) { Text( buildAnnotatedString { - withStyle(SpanStyle(color = Color.Red)) { + withStyle(SpanStyle(color = LocalRrtopColorsPalette.current.cpuSysCpuText2Fg)) { append("•") } - append("sys cpu: ") - withStyle(SpanStyle(color = Color.Red)) { + withStyle(SpanStyle(color = LocalRrtopColorsPalette.current.cpuSysCpuText1Fg)) { + append("sys cpu: ") + } + withStyle(SpanStyle(color = LocalRrtopColorsPalette.current.cpuSysCpuText2Fg)) { append(sysCpuUtilization) } append(" ") - withStyle(SpanStyle(color = Color.Green)) { + withStyle(SpanStyle(color = LocalRrtopColorsPalette.current.cpuUserCpuText2Fg)) { append("•") } - append("user cpu: ") - withStyle(SpanStyle(color = Color.Green)) { + withStyle(SpanStyle(color = LocalRrtopColorsPalette.current.cpuUserCpuText1Fg)) { + append("user cpu: ") + } + withStyle(SpanStyle(color = LocalRrtopColorsPalette.current.cpuUserCpuText2Fg)) { append(userCpuUtilization) } }, @@ -141,14 +162,22 @@ private fun CpuLegendInfo( @Composable private fun NetworkSection(uiState: MainScreenUiState, modifier: Modifier = Modifier) { - BorderedTitledBox(title = "network", modifier = modifier) { + BorderedTitledBox( + title = "network", + titleColor = LocalRrtopColorsPalette.current.networkTitleFg, + borderColor = LocalRrtopColorsPalette.current.networkBorderFg, + modifier = modifier, + ) { Column { TitledSolidPlot( firstTitle = "Total rx: ${uiState.items.lastOrNull()?.totalRx ?: ""}", + firstTitleColor = LocalRrtopColorsPalette.current.networkRxTotalTextFg, secondTitle = " Rx/s: ${uiState.items.lastOrNull()?.rxPerSecondFormatted ?: ""}", + secondTitleColor = LocalRrtopColorsPalette.current.networkRxSTextFg, plotInfo = PlotInfo( items = uiState.items, - color = Color.Red, + color = LocalRrtopColorsPalette.current.networkRxSparklineFg, + baselineColor = LocalRrtopColorsPalette.current.networkRxSparklineBaselineFg, numberFromItem = { it.rxPerSecond }, stringFromItem = { it.rxPerSecondFormatted }, ), @@ -156,10 +185,13 @@ private fun NetworkSection(uiState: MainScreenUiState, modifier: Modifier = Modi ) TitledSolidPlot( firstTitle = "Total tx: ${uiState.items.lastOrNull()?.totalTx ?: ""}", + firstTitleColor = LocalRrtopColorsPalette.current.networkTxTotalTextFg, secondTitle = " Tx/s: ${uiState.items.lastOrNull()?.txPerSecondFormatted ?: ""}", + secondTitleColor = LocalRrtopColorsPalette.current.networkTxSTextFg, plotInfo = PlotInfo( items = uiState.items, - color = Color.Blue, + color = LocalRrtopColorsPalette.current.networkTxSparklineFg, + baselineColor = LocalRrtopColorsPalette.current.networkTxSparklineBaselineFg, numberFromItem = { it.txPerSecond }, stringFromItem = { it.txPerSecondFormatted }, ), @@ -171,14 +203,22 @@ private fun NetworkSection(uiState: MainScreenUiState, modifier: Modifier = Modi @Composable private fun MemorySection(uiState: MainScreenUiState, modifier: Modifier = Modifier) { - BorderedTitledBox(title = "memory", modifier = modifier) { + BorderedTitledBox( + title = "memory", + titleColor = LocalRrtopColorsPalette.current.memoryTitleFg, + borderColor = LocalRrtopColorsPalette.current.memoryBorderFg, + modifier = modifier, + ) { Column { TitledSolidPlot( firstTitle = " Max memory: ${uiState.items.lastOrNull()?.maxMemory ?: ""}", + firstTitleColor = LocalRrtopColorsPalette.current.memoryMaxMemoryTextFg, secondTitle = "Used memory: ${uiState.items.lastOrNull()?.memoryUsageFormatted ?: ""}", + secondTitleColor = LocalRrtopColorsPalette.current.memoryUsedMemoryTextFg, plotInfo = PlotInfo( items = uiState.items, - color = Color.Blue, + color = LocalRrtopColorsPalette.current.memoryUsedMemorySparklineFg, + baselineColor = LocalRrtopColorsPalette.current.memoryUsedMemorySparklineBaselineFg, numberFromItem = { it.memoryUsage }, stringFromItem = { it.memoryUsageFormatted }, ), @@ -186,10 +226,13 @@ private fun MemorySection(uiState: MainScreenUiState, modifier: Modifier = Modif ) TitledSolidPlot( firstTitle = " Frag ratio: ${uiState.items.lastOrNull()?.fragmentationRatio ?: ""}", + firstTitleColor = LocalRrtopColorsPalette.current.memoryFragRatioTextFg, secondTitle = " RSS memory: ${uiState.items.lastOrNull()?.memoryRssFormatted ?: ""}", + secondTitleColor = LocalRrtopColorsPalette.current.memoryRssMemoryTextFg, plotInfo = PlotInfo( items = uiState.items, - color = Color.Green, + color = LocalRrtopColorsPalette.current.memoryRssMemorySparklineFg, + baselineColor = LocalRrtopColorsPalette.current.memoryRssMemorySparklineBaselineFg, numberFromItem = { it.memoryRss }, stringFromItem = { it.memoryRssFormatted }, ), @@ -201,71 +244,82 @@ private fun MemorySection(uiState: MainScreenUiState, modifier: Modifier = Modif @Composable private fun StatSection(uiState: MainScreenUiState, modifier: Modifier = Modifier) { - BorderedTitledBox(title = "stat", modifier = modifier) { + BorderedTitledBox( + title = "stat", + titleColor = LocalRrtopColorsPalette.current.statTitleFg, + borderColor = LocalRrtopColorsPalette.current.statBorderFg, + modifier = modifier, + ) { Table( TableData(uiState.items), TableConfig( - listOf( + titleColor = LocalRrtopColorsPalette.current.statTableHeaderFg, + columnConfigs = listOf( TableConfig.ColumnConfig.StringColumnConfig( title = "time", stringFromItem = { it.time }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop1Fg, weight = 2, ), TableConfig.ColumnConfig.StringColumnConfig( title = "op/s", - valueColor = Color.Blue, stringFromItem = { it.operationsPerSecondFormatted }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "user", - valueColor = Color.Blue, stringFromItem = { it.userCpuUtilizationFormatted }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "sys", - valueColor = Color.Blue, stringFromItem = { it.sysCpuUtilizationFormatted }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "mem use", stringFromItem = { it.memoryUsageFormatted }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "mem rss", stringFromItem = { it.memoryRssFormatted }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "fr rati", - valueColor = Color.Blue, stringFromItem = { it.fragmentationRatio }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "hit rate", - valueColor = Color.Blue, stringFromItem = { it.hitRateFormatted }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.ProgressColumnConfig( - filledColor = Color.Blue, - emptyColor = Color.BrightBlack, + filledColor = LocalRrtopColorsPalette.current.statTableRowGaugeFg, + emptyColor = LocalRrtopColorsPalette.current.statTableRowGaugeBg, progressFromItem = { it.hitRate / 100.0f }, ), TableConfig.ColumnConfig.StringColumnConfig( title = "keys", stringFromItem = { it.totalKeys }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "exp", stringFromItem = { it.keysToExpire }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "exp/s", - valueColor = Color.Blue, stringFromItem = { it.keysToExpirePerSecond }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "evt/s", - valueColor = Color.Blue, stringFromItem = { it.evictedKeysPerSecond }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), ), ), @@ -277,12 +331,14 @@ private fun StatSection(uiState: MainScreenUiState, modifier: Modifier = Modifie private data class PlotInfo( val items: List, val color: Color, + val baselineColor: Color = color, val numberFromItem: (T) -> Number, val stringFromItem: (T) -> String, ) @Composable private fun LabeledDottedPlot( + labelColor: Color, plotInfo: PlotInfo, endOffsetForLabels: Int, modifier: Modifier = Modifier, @@ -303,11 +359,13 @@ private fun LabeledDottedPlot( row = minValueRow, column = width - minValueText.length, string = minValueText, + foreground = labelColor, ) drawText( row = maxValueRow, column = width - maxValueText.length, string = maxValueText, + foreground = labelColor, ) } }, @@ -376,13 +434,15 @@ private fun DottedPlot( @Composable private fun TitledSolidPlot( firstTitle: String, + firstTitleColor: Color, secondTitle: String, + secondTitleColor: Color, plotInfo: PlotInfo, modifier: Modifier = Modifier, ) { Column(modifier = modifier) { - SolitPlotTitle(firstTitle, plotInfo.color) - SolitPlotTitle(secondTitle, plotInfo.color) + SolitPlotTitle(firstTitle, firstTitleColor) + SolitPlotTitle(secondTitle, secondTitleColor) SolidPlot(plotInfo, Modifier.fillMaxSize()) } } @@ -412,7 +472,7 @@ private fun SolidPlot( row = height - 1, column = 0, string = "_".repeat(startColumn), - foreground = Color.BrightBlack, + foreground = plotInfo.baselineColor, ) val minNullableValue = lastRange.minOrNull() val maxNullableValue = lastRange.maxOrNull() diff --git a/samples/rrtop/src/main/kotlin/example/screens/RawScreen.kt b/samples/rrtop/src/main/kotlin/example/screens/RawScreen.kt index be3c89647..867bfee3d 100644 --- a/samples/rrtop/src/main/kotlin/example/screens/RawScreen.kt +++ b/samples/rrtop/src/main/kotlin/example/screens/RawScreen.kt @@ -2,7 +2,7 @@ package example.screens import androidx.compose.runtime.Composable import com.jakewharton.mosaic.modifier.Modifier -import com.jakewharton.mosaic.ui.Color +import example.LocalRrtopColorsPalette import example.RawScreenUiState import example.common.BorderedTitledBox import example.common.Table @@ -11,19 +11,26 @@ import example.common.TableData @Composable fun RawScreen(uiState: RawScreenUiState, modifier: Modifier = Modifier) { - BorderedTitledBox(title = "raw info", modifier = modifier) { + BorderedTitledBox( + title = "raw info", + titleColor = LocalRrtopColorsPalette.current.rawTitleFg, + borderColor = LocalRrtopColorsPalette.current.rawBorderFg, + modifier = modifier, + ) { Table( TableData(uiState.items), TableConfig( - listOf( + titleColor = LocalRrtopColorsPalette.current.rawTableHeaderFg, + columnConfigs = listOf( TableConfig.ColumnConfig.StringColumnConfig( title = "key", stringFromItem = { it.key }, + valueColor = LocalRrtopColorsPalette.current.rawTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "value", stringFromItem = { it.value }, - valueColor = Color.Blue, + valueColor = LocalRrtopColorsPalette.current.rawTableRowTop2Fg, ), ), ), diff --git a/samples/rrtop/src/main/kotlin/example/screens/SlowScreen.kt b/samples/rrtop/src/main/kotlin/example/screens/SlowScreen.kt index 073daeccc..143697fc0 100644 --- a/samples/rrtop/src/main/kotlin/example/screens/SlowScreen.kt +++ b/samples/rrtop/src/main/kotlin/example/screens/SlowScreen.kt @@ -2,7 +2,7 @@ package example.screens import androidx.compose.runtime.Composable import com.jakewharton.mosaic.modifier.Modifier -import com.jakewharton.mosaic.ui.Color +import example.LocalRrtopColorsPalette import example.SlowScreenUiState import example.common.BorderedTitledBox import example.common.Table @@ -11,37 +11,46 @@ import example.common.TableData @Composable fun SlowScreen(uiState: SlowScreenUiState, modifier: Modifier = Modifier) { - BorderedTitledBox(title = "slow log", modifier = modifier) { + BorderedTitledBox( + title = "slow log", + titleColor = LocalRrtopColorsPalette.current.slowTitleFg, + borderColor = LocalRrtopColorsPalette.current.slowBorderFg, + modifier = modifier, + ) { Table( TableData(uiState.items), TableConfig( - listOf( + titleColor = LocalRrtopColorsPalette.current.slowTableHeaderFg, + columnConfigs = listOf( TableConfig.ColumnConfig.StringColumnConfig( title = "id", stringFromItem = { it.id }, + valueColor = LocalRrtopColorsPalette.current.slowTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "time", stringFromItem = { it.time }, - valueColor = Color.Blue, + valueColor = LocalRrtopColorsPalette.current.slowTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "exec time", stringFromItem = { it.execTime }, - valueColor = Color.Blue, + valueColor = LocalRrtopColorsPalette.current.slowTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "command", stringFromItem = { it.command }, - valueColor = Color.Blue, + valueColor = LocalRrtopColorsPalette.current.slowTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "client ip", stringFromItem = { it.clientIp }, + valueColor = LocalRrtopColorsPalette.current.slowTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "client name", stringFromItem = { it.clientName }, + valueColor = LocalRrtopColorsPalette.current.slowTableRowTop1Fg, ), ), ), diff --git a/samples/rrtop/src/main/kotlin/example/screens/StatScreen.kt b/samples/rrtop/src/main/kotlin/example/screens/StatScreen.kt index a70ef0e1c..205b89d09 100644 --- a/samples/rrtop/src/main/kotlin/example/screens/StatScreen.kt +++ b/samples/rrtop/src/main/kotlin/example/screens/StatScreen.kt @@ -2,7 +2,7 @@ package example.screens import androidx.compose.runtime.Composable import com.jakewharton.mosaic.modifier.Modifier -import com.jakewharton.mosaic.ui.Color +import example.LocalRrtopColorsPalette import example.StatScreenUiState import example.common.BorderedTitledBox import example.common.Table @@ -11,71 +11,82 @@ import example.common.TableData @Composable fun StatScreen(uiState: StatScreenUiState, modifier: Modifier = Modifier) { - BorderedTitledBox(title = "stat", modifier = modifier) { + BorderedTitledBox( + title = "stat", + titleColor = LocalRrtopColorsPalette.current.statTitleFg, + borderColor = LocalRrtopColorsPalette.current.statBorderFg, + modifier = modifier, + ) { Table( TableData(uiState.items), TableConfig( - listOf( + titleColor = LocalRrtopColorsPalette.current.statTableHeaderFg, + columnConfigs = listOf( TableConfig.ColumnConfig.StringColumnConfig( title = "time", stringFromItem = { it.time }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop1Fg, weight = 2, ), TableConfig.ColumnConfig.StringColumnConfig( title = "op/s", - valueColor = Color.Blue, stringFromItem = { it.operationsPerSecond }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "user", - valueColor = Color.Blue, stringFromItem = { it.userCpuUtilization }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "sys", - valueColor = Color.Blue, stringFromItem = { it.sysCpuUtilization }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "mem use", stringFromItem = { it.memoryUsage }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "mem rss", stringFromItem = { it.memoryRss }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "fr rati", - valueColor = Color.Blue, stringFromItem = { it.fragmentationRatio }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "hit rate", - valueColor = Color.Blue, stringFromItem = { it.hitRateFormatted }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.ProgressColumnConfig( - filledColor = Color.Blue, - emptyColor = Color.BrightBlack, + filledColor = LocalRrtopColorsPalette.current.statTableRowGaugeFg, + emptyColor = LocalRrtopColorsPalette.current.statTableRowGaugeBg, progressFromItem = { it.hitRate / 100.0f }, ), TableConfig.ColumnConfig.StringColumnConfig( title = "keys", stringFromItem = { it.totalKeys }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "exp", stringFromItem = { it.keysToExpire }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop1Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "exp/s", - valueColor = Color.Blue, stringFromItem = { it.keysToExpirePerSecond }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), TableConfig.ColumnConfig.StringColumnConfig( title = "evt/s", - valueColor = Color.Blue, stringFromItem = { it.evictedKeysPerSecond }, + valueColor = LocalRrtopColorsPalette.current.statTableRowTop2Fg, ), ), ),