1 /*
<lambda>null2 * Copyright (C) 2025 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.mechanics.demo
18
19 import androidx.compose.foundation.clickable
20 import androidx.compose.foundation.layout.Arrangement
21 import androidx.compose.foundation.layout.Column
22 import androidx.compose.foundation.layout.fillMaxWidth
23 import androidx.compose.foundation.layout.padding
24 import androidx.compose.foundation.lazy.LazyColumn
25 import androidx.compose.foundation.shape.CircleShape
26 import androidx.compose.material3.MaterialTheme
27 import androidx.compose.material3.Surface
28 import androidx.compose.material3.Text
29 import androidx.compose.runtime.Composable
30 import androidx.compose.ui.Alignment
31 import androidx.compose.ui.Modifier
32 import androidx.compose.ui.unit.dp
33 import androidx.navigation.NavController
34 import androidx.navigation.NavGraphBuilder
35 import androidx.navigation.compose.composable
36 import androidx.navigation.compose.navigation
37 import com.android.mechanics.demo.tuneable.ConfigurableDemo
38 import com.android.mechanics.demo.tuneable.Demo
39
40 /** A screen in the demo app. */
41 sealed class Screen(val identifier: String)
42
43 /** A parent screen, which lists its child screens to navigate to them. */
44 class ParentScreen(identifier: String, val children: Map<String, Screen>) : Screen(identifier)
45
46 /** A child screen, which shows some [content]. */
47 class ChildScreen(identifier: String, val content: @Composable (NavController) -> Unit) :
48 Screen(identifier)
49
50 /** A child screen, which shows a [demo]. */
51 class DemoScreen(val demo: Demo<*>) : Screen(demo.identifier)
52
53 /** Create the navigation graph for [screen]. */
54 fun NavGraphBuilder.screen(screen: Screen, navController: NavController) {
55 when (screen) {
56 is ChildScreen -> composable(screen.identifier) { screen.content(navController) }
57 is DemoScreen -> composable(screen.identifier) { screen.demo.ConfigurableDemo() }
58 is ParentScreen -> {
59 val menuRoute = "${screen.identifier}_menu"
60 navigation(startDestination = menuRoute, route = screen.identifier) {
61 // The menu to navigate to one of the children screens.
62 composable(menuRoute) { ScreenMenu(screen, navController) }
63
64 // The content of the child screens.
65 screen.children.forEach { (_, child) -> screen(child, navController) }
66 }
67 }
68 }
69 }
70
71 @Composable
ScreenMenunull72 private fun ScreenMenu(screen: ParentScreen, navController: NavController) {
73 LazyColumn(
74 Modifier.padding(horizontal = 16.dp),
75 verticalArrangement = Arrangement.spacedBy(8.dp),
76 ) {
77 screen.children.forEach { (name, child) ->
78 item {
79 Surface(
80 Modifier.fillMaxWidth(),
81 color = MaterialTheme.colorScheme.secondaryContainer,
82 shape = CircleShape,
83 ) {
84 val onClick = { navController.navigate(child.identifier) }
85 Column(
86 Modifier.clickable(onClick = onClick)
87 .padding(horizontal = 24.dp, vertical = 16.dp),
88 horizontalAlignment = Alignment.Start,
89 ) {
90 Text(name)
91 }
92 }
93 }
94 }
95 }
96 }
97