JakeWharton / mosaic

An experimental tool for building console UI in Kotlin using the Jetpack Compose compiler/runtime

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Custom layouts

DavidEdwards opened this issue · comments

Box is defined as such:

@Composable
private fun Box(isRow: Boolean, children: @Composable () -> Unit) {
	ComposeNode<BoxNode, MosaicNodeApplier>(
		factory = ::BoxNode,
		update = {
			set(isRow) {
				this.isRow = isRow
			}
		},
		content = children,
	)
}

Unfortunately MosaicNodeApplier and MosaicNode are internal.

What is the best way to implement a custom layout?

For example, if I wanted to create a Scaffold composable, like in Android. Whereby I could have a title and a content. I would like to be able to layout the Scaffold that it takes up the terminal window size.

How I intend to start it:

@Composable
fun Scaffold(
    terminal: Terminal,
    title: @Composable (TerminalScope) -> Unit,
    content: @Composable (TerminalScope) -> Unit
) {
    fun scopeFromTerminal(terminal: Terminal): TerminalScope = TerminalScope(
        width = terminal.width,
        height = terminal.height
    )

    var terminalScope by mutableStateOf(
        scopeFromTerminal(terminal)
    )

    terminal.handle(Terminal.Signal.WINCH) { signal ->
        terminalScope = scopeFromTerminal(terminal)
    }

    title.invoke(terminalScope)

    content.invoke(terminalScope)
}

So this is somewhat of a composite feature request. There are multiple things we may or may not need in order to support this:

  • The ability to determine the terminal size (a CompositionLocal is likely)
  • One of:
    • The ability to create a custom layout where you can measure and place your children.
    • #11

I'm going to split out the terminal size feature request and leave this one for custom layouts.

This is done. All that's left is #11.