diff --git a/connector/composeApp/build.gradle.kts b/connector/composeApp/build.gradle.kts index 01bafff..09f3f36 100644 --- a/connector/composeApp/build.gradle.kts +++ b/connector/composeApp/build.gradle.kts @@ -8,6 +8,7 @@ plugins { kotlin { jvm("desktop") + jvmToolchain(21) sourceSets { val desktopMain by getting @@ -24,6 +25,34 @@ kotlin { desktopMain.dependencies { implementation(compose.desktop.currentOs) implementation("org.jetbrains.compose.material3:material3-desktop:1.6.1") + + // Voyager - Navigation + val voyagerVersion = "1.0.0" + + // Multiplatform + + // Navigator + implementation("cafe.adriel.voyager:voyager-navigator:$voyagerVersion") + + // Screen Model + implementation("cafe.adriel.voyager:voyager-screenmodel:$voyagerVersion") + + // BottomSheetNavigator + implementation("cafe.adriel.voyager:voyager-bottom-sheet-navigator:$voyagerVersion") + + // TabNavigator + implementation("cafe.adriel.voyager:voyager-tab-navigator:$voyagerVersion") + + // Transitions + implementation("cafe.adriel.voyager:voyager-transitions:$voyagerVersion") + + // Desktop + Android + + // Kodein integration + implementation("cafe.adriel.voyager:voyager-kodein:$voyagerVersion") + + // RxJava integration + implementation("cafe.adriel.voyager:voyager-rxjava:$voyagerVersion") } } } diff --git a/connector/composeApp/src/desktopMain/kotlin/About.kt b/connector/composeApp/src/desktopMain/kotlin/About.kt new file mode 100644 index 0000000..7530dbf --- /dev/null +++ b/connector/composeApp/src/desktopMain/kotlin/About.kt @@ -0,0 +1,36 @@ + +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import cafe.adriel.voyager.navigator.tab.Tab +import cafe.adriel.voyager.navigator.tab.TabOptions +import connector.composeapp.generated.resources.Res +import connector.composeapp.generated.resources.info_24px +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource + +class About : Tab { + @OptIn(ExperimentalResourceApi::class) + override val options: TabOptions + @Composable + get() { + val title = "About" + val icon = painterResource(Res.drawable.info_24px) + + return remember { + TabOptions( + index = 0u, + title = title, + icon = icon, + ) + } + } + + @Composable + override fun Content() { + Column { + Text("About") + } + } +} diff --git a/connector/composeApp/src/desktopMain/kotlin/App.kt b/connector/composeApp/src/desktopMain/kotlin/App.kt index 76b58c7..5c380ba 100644 --- a/connector/composeApp/src/desktopMain/kotlin/App.kt +++ b/connector/composeApp/src/desktopMain/kotlin/App.kt @@ -1,27 +1,22 @@ - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Menu -import androidx.compose.material.icons.outlined.Edit -import androidx.compose.material.icons.outlined.Settings import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import connector.composeapp.generated.resources.* +import cafe.adriel.voyager.navigator.tab.CurrentTab +import cafe.adriel.voyager.navigator.tab.LocalTabNavigator +import cafe.adriel.voyager.navigator.tab.Tab +import cafe.adriel.voyager.navigator.tab.TabNavigator import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.jetbrains.compose.resources.ExperimentalResourceApi -import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.ui.tooling.preview.Preview import theme.AppTheme @@ -30,49 +25,35 @@ import theme.AppTheme @Preview fun App() { AppTheme { - var showContent by remember { mutableStateOf(false) } - Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - AppScaffold { - Button(onClick = { showContent = !showContent }) { - Text("Click me!") - } - AnimatedVisibility(showContent) { - val greeting = remember { Greeting().greet() } - Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Image(painterResource(Res.drawable.compose_multiplatform), null) - Text("Compose: $greeting") - } - } - } - } + AppScaffold() } } @Composable -fun AppScaffold(content: @Composable() () -> Unit) { +fun AppScaffold() { val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) val scope = rememberCoroutineScope() - Scaffold( - topBar = { - TopBar(drawerState, scope) - }, - ) { innerPadding -> - Column( - modifier = Modifier.padding(innerPadding) - ) { - NavigationDrawer(drawerState) { + TabNavigator(Projects) { + Scaffold( + topBar = { + TopBar(drawerState, scope) + }, + content = { innerPadding -> Column( - verticalArrangement = Arrangement.spacedBy(16.dp) + modifier = Modifier.padding(innerPadding) ) { - content() - Text("Test") + NavigationDrawer(drawerState) { + CurrentTab() + } } } - } + ) } } + + /** * Component for the bar on top of the screen */ @@ -128,48 +109,18 @@ fun NavigationDrawer( ModalDrawerSheet { Column(modifier = Modifier.verticalScroll(rememberScrollState()) ) { Text("Project Name...", modifier = Modifier.padding(16.dp)) - NavigationDrawerItem( - label = { Text(text = "Projects") }, - icon = { Icon(painterResource(Res.drawable.folder_24px), null) }, - selected = false, - onClick = { /* TODO */ }, - ) + TabNavigationItem(Projects) HorizontalDivider() Text("Tester", modifier = Modifier.padding(16.dp)) - NavigationDrawerItem( - label = { Text(text = "Procedures") }, - icon = { Icon(imageVector = Icons.Outlined.Edit, null) }, - selected = false, - onClick = { /* TODO */ }, - ) - NavigationDrawerItem( - label = { Text(text = "Simulator Test") }, - icon = { Icon(painterResource(Res.drawable.check_box_24px), null) }, - selected = false, - onClick = { /* TODO */ }, - ) - NavigationDrawerItem( - label = { Text(text = "Test Results") }, - icon = { Icon(painterResource(Res.drawable.history_24px), null) }, - selected = false, - onClick = { /* TODO */ }, - ) + TabNavigationItem(Procedures()) + TabNavigationItem(SimulatorTest()) + TabNavigationItem(TestResults()) HorizontalDivider() Text("Application", modifier = Modifier.padding(16.dp)) - NavigationDrawerItem( - label = { Text(text = "Settings") }, - icon = { Icon(imageVector = Icons.Outlined.Settings, null) }, - selected = false, - onClick = { /* TODO */ }, - ) - NavigationDrawerItem( - label = { Text(text = "About") }, - icon = { Icon(painterResource(Res.drawable.info_24px), null) }, - selected = false, - onClick = { /* TODO */ }, - ) + TabNavigationItem(Settings()) + TabNavigationItem(About()) } } } @@ -177,3 +128,18 @@ fun NavigationDrawer( content() } } + +/** + * Creates button in NavigationDrawer + */ +@Composable +private fun TabNavigationItem(tab: Tab) { + val tabNavigator = LocalTabNavigator.current + + NavigationDrawerItem( + label = { Text(tab.options.title) }, + icon = { tab.options.icon?.let { Icon(it, null) } }, + selected = tabNavigator.current == tab, + onClick = { tabNavigator.current = tab }, + ) +} diff --git a/connector/composeApp/src/desktopMain/kotlin/Procedures.kt b/connector/composeApp/src/desktopMain/kotlin/Procedures.kt new file mode 100644 index 0000000..31464d4 --- /dev/null +++ b/connector/composeApp/src/desktopMain/kotlin/Procedures.kt @@ -0,0 +1,55 @@ +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Edit +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import cafe.adriel.voyager.navigator.tab.Tab +import cafe.adriel.voyager.navigator.tab.TabOptions +import connector.composeapp.generated.resources.Res +import connector.composeapp.generated.resources.compose_multiplatform +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource + +class Procedures : Tab { + override val options: TabOptions + @Composable + get() { + val title = "Procedures" + val icon = rememberVectorPainter(Icons.Outlined.Edit) + + return remember { + TabOptions( + index = 1u, + title = title, + icon = icon, + ) + } + } + + + @OptIn(ExperimentalResourceApi::class) + @Composable + override fun Content() { + var showContent by remember { mutableStateOf(false) } + + Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { + Button(onClick = { showContent = !showContent }) { + Text("Click me!") + } + AnimatedVisibility(showContent) { + val greeting = remember { Greeting().greet() } + Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { + Image(painterResource(Res.drawable.compose_multiplatform), null) + Text("Compose: $greeting") + } + } + } + } +} diff --git a/connector/composeApp/src/desktopMain/kotlin/Projects.kt b/connector/composeApp/src/desktopMain/kotlin/Projects.kt new file mode 100644 index 0000000..d765520 --- /dev/null +++ b/connector/composeApp/src/desktopMain/kotlin/Projects.kt @@ -0,0 +1,35 @@ +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import cafe.adriel.voyager.navigator.tab.Tab +import cafe.adriel.voyager.navigator.tab.TabOptions +import connector.composeapp.generated.resources.Res +import connector.composeapp.generated.resources.folder_24px +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource + +object Projects : Tab { + @OptIn(ExperimentalResourceApi::class) + override val options: TabOptions + @Composable + get() { + val title = "Projects" + val icon = painterResource(Res.drawable.folder_24px) + + return remember { + TabOptions( + index = 0u, + title = title, + icon = icon, + ) + } + } + + @Composable + override fun Content() { + Column { + Text("Projects") + } + } +} diff --git a/connector/composeApp/src/desktopMain/kotlin/Settings.kt b/connector/composeApp/src/desktopMain/kotlin/Settings.kt new file mode 100644 index 0000000..9cc35c4 --- /dev/null +++ b/connector/composeApp/src/desktopMain/kotlin/Settings.kt @@ -0,0 +1,36 @@ + +import androidx.compose.foundation.layout.Column +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import cafe.adriel.voyager.navigator.tab.Tab +import cafe.adriel.voyager.navigator.tab.TabOptions +import org.jetbrains.compose.resources.ExperimentalResourceApi + +class Settings : Tab { + @OptIn(ExperimentalResourceApi::class) + override val options: TabOptions + @Composable + get() { + val title = "Settings" + val icon = rememberVectorPainter(Icons.Outlined.Settings) + + return remember { + TabOptions( + index = 4u, + title = title, + icon = icon, + ) + } + } + + @Composable + override fun Content() { + Column { + Text("Settings") + } + } +} diff --git a/connector/composeApp/src/desktopMain/kotlin/SimulatorTest.kt b/connector/composeApp/src/desktopMain/kotlin/SimulatorTest.kt new file mode 100644 index 0000000..8a97029 --- /dev/null +++ b/connector/composeApp/src/desktopMain/kotlin/SimulatorTest.kt @@ -0,0 +1,36 @@ + +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import cafe.adriel.voyager.navigator.tab.Tab +import cafe.adriel.voyager.navigator.tab.TabOptions +import connector.composeapp.generated.resources.Res +import connector.composeapp.generated.resources.check_box_24px +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource + +class SimulatorTest : Tab { + @OptIn(ExperimentalResourceApi::class) + override val options: TabOptions + @Composable + get() { + val title = "Simulator Test" + val icon = painterResource(Res.drawable.check_box_24px) + + return remember { + TabOptions( + index = 2u, + title = title, + icon = icon, + ) + } + } + + @Composable + override fun Content() { + Column { + Text("Simulator Test") + } + } +} diff --git a/connector/composeApp/src/desktopMain/kotlin/TestResults.kt b/connector/composeApp/src/desktopMain/kotlin/TestResults.kt new file mode 100644 index 0000000..08680ba --- /dev/null +++ b/connector/composeApp/src/desktopMain/kotlin/TestResults.kt @@ -0,0 +1,36 @@ + +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import cafe.adriel.voyager.navigator.tab.Tab +import cafe.adriel.voyager.navigator.tab.TabOptions +import connector.composeapp.generated.resources.Res +import connector.composeapp.generated.resources.history_24px +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource + +class TestResults : Tab { + @OptIn(ExperimentalResourceApi::class) + override val options: TabOptions + @Composable + get() { + val title = "Test Results" + val icon = painterResource(Res.drawable.history_24px) + + return remember { + TabOptions( + index = 3u, + title = title, + icon = icon, + ) + } + } + + @Composable + override fun Content() { + Column { + Text("Test Results") + } + } +} diff --git a/connector/shared/build.gradle.kts b/connector/shared/build.gradle.kts index b33a8fa..fcc6013 100644 --- a/connector/shared/build.gradle.kts +++ b/connector/shared/build.gradle.kts @@ -1,12 +1,13 @@ plugins { alias(libs.plugins.kotlinMultiplatform) - + } kotlin { jvm() - + jvmToolchain(21) + sourceSets { commonMain.dependencies { // put your Multiplatform dependencies here