Skip to content

Commit 4f9f92b

Browse files
committed
Replace color legend with tooltip display on node hover
1 parent a9a44e9 commit 4f9f92b

File tree

4 files changed

+75
-101
lines changed

4 files changed

+75
-101
lines changed

workflow-trace-viewer/src/jvmMain/kotlin/com/squareup/workflow1/traceviewer/App.kt

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import androidx.compose.ui.layout.onGloballyPositioned
2020
import androidx.compose.ui.unit.IntSize
2121
import com.squareup.workflow1.traceviewer.model.Node
2222
import com.squareup.workflow1.traceviewer.model.NodeUpdate
23-
import com.squareup.workflow1.traceviewer.ui.ColorLegend
2423
import com.squareup.workflow1.traceviewer.ui.RightInfoPanel
2524
import com.squareup.workflow1.traceviewer.ui.control.DisplayDevices
2625
import com.squareup.workflow1.traceviewer.ui.control.FileDump
@@ -39,7 +38,7 @@ import io.github.vinceglb.filekit.PlatformFile
3938
internal fun App(
4039
modifier: Modifier = Modifier
4140
) {
42-
var appWindowSize by remember { mutableStateOf(IntSize(0,0)) }
41+
var appWindowSize by remember { mutableStateOf(IntSize(0, 0)) }
4342
var selectedNode by remember { mutableStateOf<NodeUpdate?>(null) }
4443
var frameSize by remember { mutableIntStateOf(0) }
4544
var rawRenderPass by remember { mutableStateOf("") }
@@ -178,12 +177,6 @@ internal fun App(
178177
)
179178
}
180179

181-
if (active) {
182-
ColorLegend(
183-
modifier = Modifier.align(Alignment.BottomEnd)
184-
)
185-
}
186-
187180
RightInfoPanel(
188181
selectedNode = selectedNode,
189182
modifier = Modifier

workflow-trace-viewer/src/jvmMain/kotlin/com/squareup/workflow1/traceviewer/ui/ColorLegend.kt

Lines changed: 0 additions & 62 deletions
This file was deleted.

workflow-trace-viewer/src/jvmMain/kotlin/com/squareup/workflow1/traceviewer/ui/WorkflowTree.kt

Lines changed: 73 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package com.squareup.workflow1.traceviewer.ui
33
import androidx.compose.foundation.background
44
import androidx.compose.foundation.border
55
import androidx.compose.foundation.clickable
6+
import androidx.compose.foundation.hoverable
7+
import androidx.compose.foundation.interaction.MutableInteractionSource
8+
import androidx.compose.foundation.interaction.collectIsHoveredAsState
69
import androidx.compose.foundation.layout.Arrangement
710
import androidx.compose.foundation.layout.Box
811
import androidx.compose.foundation.layout.Column
@@ -14,9 +17,12 @@ import androidx.compose.foundation.shape.RoundedCornerShape
1417
import androidx.compose.material.Text
1518
import androidx.compose.runtime.Composable
1619
import androidx.compose.runtime.LaunchedEffect
20+
import androidx.compose.runtime.getValue
21+
import androidx.compose.runtime.remember
1722
import androidx.compose.ui.Alignment
1823
import androidx.compose.ui.ExperimentalComposeUiApi
1924
import androidx.compose.ui.Modifier
25+
import androidx.compose.ui.draw.clip
2026
import androidx.compose.ui.geometry.Offset
2127
import androidx.compose.ui.graphics.Color
2228
import androidx.compose.ui.input.pointer.PointerEventType
@@ -27,6 +33,7 @@ import androidx.compose.ui.layout.positionInRoot
2733
import androidx.compose.ui.unit.dp
2834
import androidx.compose.ui.unit.sp
2935
import com.squareup.workflow1.traceviewer.model.Node
36+
import com.squareup.workflow1.traceviewer.model.NodeState
3037
import com.squareup.workflow1.traceviewer.model.NodeUpdate
3138

3239
/**
@@ -286,44 +293,81 @@ private fun DrawNode(
286293
onExpandToggle: (Node) -> Unit,
287294
storeNodeLocation: (Node, Offset) -> Unit
288295
) {
296+
val interactionSource = remember { MutableInteractionSource() }
297+
val isHovered by interactionSource.collectIsHoveredAsState()
298+
289299
val nodeUpdate = NodeUpdate.create(
290300
current = node,
291301
past = nodePast,
292302
isAffected = isAffected
293303
)
294304

295-
Box(
296-
modifier = Modifier
297-
.background(nodeUpdate.state.color)
298-
.clickable {
299-
onNodeSelect(nodeUpdate)
300-
}
301-
.onPointerEvent(PointerEventType.Press) {
302-
if (it.buttons.isSecondaryPressed) {
303-
onExpandToggle(node)
305+
Box {
306+
Box(
307+
modifier = Modifier
308+
.hoverable(interactionSource)
309+
.background(nodeUpdate.state.color)
310+
.clickable {
311+
onNodeSelect(nodeUpdate)
304312
}
305-
}
306-
.padding(16.dp)
307-
.onGloballyPositioned { coords ->
308-
val offsetToTopLeft = coords.positionInRoot()
309-
val offsetToCenter = Offset(
310-
x = offsetToTopLeft.x + coords.size.width / 2,
311-
y = offsetToTopLeft.y + coords.size.height / 2
312-
)
313-
storeNodeLocation(node, offsetToCenter)
314-
}
315-
) {
316-
Column(horizontalAlignment = Alignment.CenterHorizontally) {
317-
Row(
318-
verticalAlignment = Alignment.CenterVertically,
319-
horizontalArrangement = Arrangement.spacedBy(4.dp)
320-
) {
321-
if (node.children.isNotEmpty()) {
322-
Text(text = if (isExpanded) "" else "")
313+
.onPointerEvent(PointerEventType.Press) {
314+
if (it.buttons.isSecondaryPressed) {
315+
onExpandToggle(node)
316+
}
323317
}
324-
Text(text = node.name)
318+
.padding(16.dp)
319+
.onGloballyPositioned { coords ->
320+
val offsetToTopLeft = coords.positionInRoot()
321+
val offsetToCenter = Offset(
322+
x = offsetToTopLeft.x + coords.size.width / 2,
323+
y = offsetToTopLeft.y + coords.size.height / 2
324+
)
325+
storeNodeLocation(node, offsetToCenter)
326+
}
327+
) {
328+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
329+
Row(
330+
verticalAlignment = Alignment.CenterVertically,
331+
horizontalArrangement = Arrangement.spacedBy(4.dp)
332+
) {
333+
if (node.children.isNotEmpty()) {
334+
Text(text = if (isExpanded) "" else "")
335+
}
336+
Text(text = node.name)
337+
}
338+
Text(text = "ID: ${node.id}")
325339
}
326-
Text(text = "ID: ${node.id}")
327340
}
341+
342+
if (isHovered) {
343+
NodeTooltip(
344+
nodeState = nodeUpdate.state,
345+
modifier = Modifier
346+
.align(Alignment.TopEnd)
347+
.background(nodeUpdate.state.color)
348+
)
349+
}
350+
}
351+
}
352+
353+
/**
354+
* A tooltip that appears on hover showing the node state type
355+
*/
356+
@Composable
357+
private fun NodeTooltip(
358+
nodeState: NodeState,
359+
modifier: Modifier = Modifier
360+
) {
361+
Box(
362+
modifier = modifier
363+
.clip(RoundedCornerShape(4.dp))
364+
.background(Color.Black.copy(alpha = 0.3f))
365+
.padding(horizontal = 8.dp, vertical = 4.dp)
366+
) {
367+
Text(
368+
text = nodeState.name,
369+
color = Color.White,
370+
fontSize = 12.sp
371+
)
328372
}
329373
}

workflow-trace-viewer/src/jvmMain/kotlin/com/squareup/workflow1/traceviewer/util/SandboxBackground.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import androidx.compose.runtime.Composable
99
import androidx.compose.ui.Alignment
1010
import androidx.compose.ui.Modifier
1111
import androidx.compose.ui.geometry.Offset
12-
import androidx.compose.ui.graphics.TransformOrigin
1312
import androidx.compose.ui.graphics.graphicsLayer
1413
import androidx.compose.ui.input.pointer.PointerEventType
1514
import androidx.compose.ui.input.pointer.pointerInput
@@ -48,7 +47,7 @@ internal fun SandboxBackground(
4847
val pointerInput = event.changes.first()
4948
val pointerOffsetToCenter = Offset(
5049
// For some reason using 1.5 made zooming more natural than 2
51-
x = pointerInput.position.x - appWindowSize.width / (3/2),
50+
x = pointerInput.position.x - appWindowSize.width / (3 / 2),
5251
y = pointerInput.position.y - appWindowSize.height / 2
5352
)
5453
val scrollDelta = pointerInput.scrollDelta.y

0 commit comments

Comments
 (0)