JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
15.26k stars 1.11k forks source link

Change position of MenuBar #4838

Closed guiiamorim closed 1 month ago

guiiamorim commented 1 month ago

Hi, I'm facing a problem when creating a MenuBar on a transparent window. I hoped that would be possible to place the menubar below my custom titlebar, but it shows above it. Is there a way to customize the position of the menubar?

@Composable
@Preview
fun App() {
    MaterialTheme {
        Box(
            modifier = Modifier.fillMaxSize()
                .background(Color.hsl(232F, .37F, .08F))
                .padding(8.dp),
        ) {
            Row(
                Modifier.fillMaxSize(),
            ) {
                Surface(
                    Modifier.weight(.7F)
                        .fillMaxHeight(),
                    shape = RoundedCornerShape(4.dp)
                ) {
                    Box(
                        Modifier.background(Color.hsl(232F, .38F, .12F))
                            .fillMaxHeight()
                            .padding(4.dp),
                    ) {

                    }
                }
                Spacer(Modifier.width(4F.dp))
                Surface(
                    Modifier.weight(2F)
                        .fillMaxHeight(),
                    shape = RoundedCornerShape(4.dp)
                ) {
                    Box(
                        Modifier
                            .background(Color.hsl(232F, .38F, .12F))
                            .fillMaxHeight()
                            .padding(4.dp),
                    ) {

                    }
                }
                Spacer(Modifier.width(4F.dp))
                Surface(
                    Modifier.weight(1F)
                        .fillMaxHeight(),
                    shape = RoundedCornerShape(4.dp)
                ) {
                    Box(
                        Modifier.background(Color.hsl(232F, .38F, .12F))
                            .fillMaxHeight()
                            .padding(4.dp),
                    ) {

                    }
                }
            }
        }
    }
}

@Composable
fun WindowScope.AppWindowTitleBar(
    state: WindowState,
    title: String,
    onClose: () -> Unit,
    onMinimize: () -> Unit = { state.isMinimized = state.isMinimized.not() },
    onMaximize: () -> Unit = {
        state.placement = if (state.placement == WindowPlacement.Maximized)
            WindowPlacement.Floating else WindowPlacement.Maximized
    },
) {
    Box(
        Modifier.fillMaxWidth()
            .background(Color.hsl(233F, .4F, .04F))
    ) {
        WindowDraggableArea(Modifier.fillMaxWidth()) {
            Row(Modifier.align(Alignment.TopEnd).fillMaxWidth().padding(horizontal = 8.dp)) {
                Box(Modifier.align(Alignment.CenterVertically)) {
                    Text(title, color = Color.White)
                }
                Spacer(Modifier.weight(1F))

                IconButton(onClick = onMinimize) {
                    Icon(Icons.Outlined.Minimize, "Minimizar", tint = Color.White)
                }

                val isFloating = state.placement == WindowPlacement.Floating
                IconButton(onClick = onMaximize) {
                    Icon(
//                        if (isFloating) Icons.Outlined.Maximize else SelectedWindow,
                        Icons.Outlined.Maximize,
                        "Maximizar",
                        tint = Color.White
                    )
                }

                IconButton(onClick = onClose) {
                    Icon(Icons.Outlined.Close, "Close", tint = Color.White)
                }
            }
        }
    }
}

fun main() = application {
    val state = rememberWindowState(size = DpSize(1280.dp, 800.dp), position = WindowPosition(Alignment.Center))
    val roundedCorners = state.placement == WindowPlacement.Floating

    Window(
        onCloseRequest = ::exitApplication,
        state = state,
        title = "FreeWorship",
        undecorated = true,
        transparent = true,
    ) {
        window.minimumSize = Dimension(1280, 800)

        Surface(
            modifier = Modifier.fillMaxSize(),
            shape = if (roundedCorners) RoundedCornerShape(6.dp) else RoundedCornerShape(0.dp),

            ) {
            Column {
                AppWindowTitleBar(state, "FreeWorship", ::exitApplication)
                MenuBar {
                    Menu("Arquivo") {}
                }
                App()
            }
        }
    }
}

image

mazunin-v-jb commented 1 month ago

@guiiamorim hello! Could you provide information about Kotlin and Compose versions of your project as well as OS and Java version?

guiiamorim commented 1 month ago

OS: Ubuntu 24.04 Java: openjdk 21.0.3 2024-04-16 OpenJDK Runtime Environment (build 21.0.3+9-Ubuntu-1ubuntu1) OpenJDK 64-Bit Server VM (build 21.0.3+9-Ubuntu-1ubuntu1, mixed mode, sharing)

Compose: 1.6.0 Kotlin: 1.9.22

igordmn commented 1 month ago

If you use a custom titleBar, you should also implement a custom MenuBar yourself.

The built-in MenuBar by design is always attached to the top of the window, or to the top of the screen (depending on the OS).

Placing MenuBar in other places is only possible if we add a new standalone component, with its own design (you can create a separate issue for that).