using Compose (multiplatform for desktop and web) ...
# compose
w
using Compose (multiplatform for desktop and web) how do I create a composable component inside a canvas? What I am trying to achieve is to draw a diagram, but for some of the texts (and other things), the user should be able to edit that text So, my idea was to make the text actually a textfield (but with custom styling to remove pretty much everything about style) so that the user can just edit it like any other textfield I tried to make a Canvas and inside its draw method, I want to render certain components like a text field:
Copy code
@Preview
@Composable
fun MyComponent() {
	var text by remember { mutableStateOf("Hello") }
	
	Column {
		TextField(
			value = text,
			onValueChange = { text = it },
			label = { Text("Label") }
		)
		
		Canvas(modifier = Modifier.fillMaxSize()) {
			val canvasQuadrantSize = size / 2F
			drawRect(
				color = Color.Magenta,
				size = canvasQuadrantSize
			)
			
			// error @Composable invocations can only happen from the context of a @Composable function
//			TextField(
//				value = text,
//				onValueChange = { text = it },
//				label = { Text("Label") }
//			)
		}
	}
}
I am not quite sure what approach I should take to make this possible especially taking into account that the component should also be affected by all the transformations that take place inside the canvas render, such as scaling and translation
z
The short answer is that, like the compiler says, you can't do this. A composable is a complex thing that can measure itself, have composable children that it measures and places, and then draw itself and its children. A
Canvas
block on the other hand is a subset of that and can only draw pixels. It can't even have its own state (although
drawWithCache
can, kind of).
So what you'd probably want to do for this sort of thing is use a
Box
or a custom layout to place your other composables, then use a
Canvas
or one of the draw modifiers to draw below them.
A (fairly complex) example of a diagramming library that supports composables in the diagram is https://github.com/zach-klippenstein/compose-seqdiag
w
I see, so, essentially: try to move, scale, and position the components through the "normal" components primarily looking at the box and using modifiers like offset and then add the fancy graphics to the draw modifiers but dont let them decide positioning of the component right?
z
You could do layout with modifiers, but if you're doing a lot of custom logic to figure out where to put diagram components, it might be easier to just do a custom layout
The custom layout can then also publish whatever layout results are needed by the draw logic
w
what I am thinking of is something like draw.io (or diagrams.net) where the user can freely move the components on screens so arbitrary positioning is a must I assume it wouldn't be too hard to apply the logic using boxes and modifiers it might prove a bit too difficult for the compose engine to apply the re-rendering of the entire diagram on every mouse drag event
so performance wise, it might not be really great, but on the other hand, I dont expect really large scale diagrams anyway
do you have a link to this "custom layout"? (I am trying out compose for the first time, so not familiar yet with all the different features)
z
it might prove a bit too difficult for the compose engine to apply the re-rendering of the entire diagram on every mouse drag event
it shouldn't, that's a large part of its job
if modifiers work for your use case though, great
just make sure to use
offset { }
not
offset()
to avoid recomposing
w
hmm... ill keep that in mind
thanks
132 Views