diff --git a/examples/imageviewer/desktopApp/src/jvmMain/kotlin/example/imageviewer/Main.kt b/examples/imageviewer/desktopApp/src/jvmMain/kotlin/example/imageviewer/Main.kt index 36fdf3914f..aca2455c7a 100644 --- a/examples/imageviewer/desktopApp/src/jvmMain/kotlin/example/imageviewer/Main.kt +++ b/examples/imageviewer/desktopApp/src/jvmMain/kotlin/example/imageviewer/Main.kt @@ -1,8 +1,86 @@ package example.imageviewer +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.awt.ComposePanel +import androidx.compose.ui.graphics.Color import androidx.compose.ui.window.application import example.imageviewer.view.ImageViewerDesktop +import java.awt.Color.CYAN +import java.awt.Graphics +import java.awt.Graphics2D +import javax.swing.JComponent +import javax.swing.JFrame +import javax.swing.JLayeredPane +import javax.swing.JLayeredPane.DEFAULT_LAYER +import javax.swing.JLayeredPane.POPUP_LAYER +import javax.swing.JPanel +import javax.swing.JSplitPane +import javax.swing.OverlayLayout +import javax.swing.SwingUtilities fun main() = application { ImageViewerDesktop() } + +fun main2() { + System.setProperty("compose.swing.render.on.graphics", "true") + SwingUtilities.invokeLater { + val composePanel = ComposePanel().apply { + setContent { + Box(modifier = Modifier.background(Color.Black).fillMaxSize()) + } + } + + + val popup = object : JComponent() { + init { + isOpaque = false + } + + override fun paintComponent(g: Graphics?) { + val scratchGraphics = g?.create() as? Graphics2D ?: return + try { + scratchGraphics.color = java.awt.Color.WHITE + scratchGraphics.fillRoundRect(5, 5, 90, 50, 16, 16) + + scratchGraphics.color = java.awt.Color.BLACK + scratchGraphics.drawString("Popup", 30, 30) + } finally { + scratchGraphics.dispose() + } + } + } + + + val rightPanel = JLayeredPane() + rightPanel.layout = OverlayLayout(rightPanel) + rightPanel.add(composePanel) + rightPanel.add(popup) + + rightPanel.setLayer(composePanel, DEFAULT_LAYER) + rightPanel.setLayer(popup, POPUP_LAYER) + + + val leftPanel = JPanel().apply { background = CYAN } + + + val splitter = JSplitPane( + JSplitPane.HORIZONTAL_SPLIT, + true, + leftPanel, + rightPanel + ).apply { + setDividerLocation(500) + } + + + JFrame().apply { + add(splitter) + setSize(600, 600) + isVisible = true + } + } +} diff --git a/examples/imageviewer/iosApp/iosApp/ContentView.swift b/examples/imageviewer/iosApp/iosApp/ContentView.swift index f02b93ebde..cc6b8d74d7 100644 --- a/examples/imageviewer/iosApp/iosApp/ContentView.swift +++ b/examples/imageviewer/iosApp/iosApp/ContentView.swift @@ -7,10 +7,6 @@ struct ContentView: View { ZStack { ComposeView() .ignoresSafeArea(.all) // Compose has own keyboard handler - VStack { - gradient.ignoresSafeArea(edges: .top).frame(height: 0) - Spacer() - } }.preferredColorScheme(.dark) } } diff --git a/examples/imageviewer/shared/build.gradle.kts b/examples/imageviewer/shared/build.gradle.kts index a473a24a34..6ae953121c 100755 --- a/examples/imageviewer/shared/build.gradle.kts +++ b/examples/imageviewer/shared/build.gradle.kts @@ -31,6 +31,7 @@ kotlin { implementation(compose.runtime) implementation(compose.foundation) implementation(compose.material) + implementation(compose.material3) //implementation(compose.materialIconsExtended) // TODO not working on iOS for now @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) implementation(compose.components.resources) diff --git a/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/ImageViewer.common.kt b/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/ImageViewer.common.kt index 540107d5c7..fafb019946 100644 --- a/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/ImageViewer.common.kt +++ b/examples/imageviewer/shared/src/commonMain/kotlin/example/imageviewer/ImageViewer.common.kt @@ -1,13 +1,34 @@ package example.imageviewer -import androidx.compose.animation.* -import androidx.compose.animation.core.tween -import androidx.compose.runtime.* -import androidx.compose.runtime.saveable.listSaver -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.snapshots.SnapshotStateList -import example.imageviewer.model.* -import example.imageviewer.view.* +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeContent +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp enum class ExternalImageViewerEvent { Next, @@ -19,108 +40,105 @@ enum class ExternalImageViewerEvent { fun ImageViewerCommon( dependencies: Dependencies ) { - CompositionLocalProvider( - LocalLocalization provides dependencies.localization, - LocalNotification provides dependencies.notification, - LocalImageProvider provides dependencies.imageProvider, - LocalInternalEvents provides dependencies.externalEvents, - LocalSharePicture provides dependencies.sharePicture, - ) { - ImageViewerWithProvidedDependencies(dependencies.pictures) + MaterialTheme { + Box(Modifier.fillMaxSize().background(Color.White)) { + CommonDialog() + //NaturalScrolling() + //DynamicType() + //TextFieldCapitalization() + //TestFramework() + } } } -@OptIn(ExperimentalAnimationApi::class) @Composable -fun ImageViewerWithProvidedDependencies( - pictures: SnapshotStateList -) { - // rememberSaveable is required to properly handle Android configuration changes (such as device rotation) - val selectedPictureIndex = rememberSaveable { mutableStateOf(0) } - val navigationStack = rememberSaveable( - saver = listSaver, Page>( - restore = { NavigationStack(*it.toTypedArray()) }, - save = { it.stack }, - ) - ) { - NavigationStack(GalleryPage()) +fun CommonDialog() { + Box(Modifier.fillMaxSize().windowInsetsPadding(WindowInsets.safeContent)) { + var isDialogOpen by remember { mutableStateOf(false) } + Button(onClick = { + isDialogOpen = true + }) { + Text("Open") + } + if (isDialogOpen) { + AlertDialog( + onDismissRequest = { isDialogOpen = false }, + confirmButton = { + Button(onClick = { isDialogOpen = false }) { + Text("OK") + } + }, + title = { Text("Alert Dialog") }, + text = { Text("Lorem Ipsum") }, + ) + } } +} - val externalEvents = LocalInternalEvents.current - LaunchedEffect(Unit) { - externalEvents.collect { - if (it == ExternalImageViewerEvent.ReturnBack) { - navigationStack.back() - } + +@Composable +fun NaturalScrolling() { + val items = (1..30).map { "Item $it" } + LazyColumn { + items(items) { + Text( + text = it, + fontSize = 30.sp, + modifier = Modifier.padding(start = 20.dp) + ) } } +} - AnimatedContent(targetState = navigationStack.lastWithIndex(), transitionSpec = { - val previousIdx = initialState.index - val currentIdx = targetState.index - val multiplier = if (previousIdx < currentIdx) 1 else -1 - if (initialState.value is GalleryPage && targetState.value is MemoryPage) { - fadeIn() with fadeOut(tween(durationMillis = 500, 500)) - } else if (initialState.value is MemoryPage && targetState.value is GalleryPage) { - fadeIn() with fadeOut(tween(delayMillis = 150)) - } else { - slideInHorizontally { w -> multiplier * w } with - slideOutHorizontally { w -> multiplier * -1 * w } - } - }) { (_, page) -> - when (page) { - is GalleryPage -> { - GalleryScreen( - pictures = pictures, - selectedPictureIndex = selectedPictureIndex, - onClickPreviewPicture = { previewPictureIndex -> - navigationStack.push(MemoryPage(previewPictureIndex)) - } - ) { - navigationStack.push(CameraPage()) - } - } +@Composable +fun DynamicType() { + Text("This is some sample text", fontSize = 30.sp) +} - is FullScreenPage -> { - FullscreenImageScreen( - picture = pictures[page.pictureIndex], - back = { - navigationStack.back() - } - ) - } +@Composable +fun TextFieldCapitalization() { + var text by remember { mutableStateOf("") } + TextField( + value = text, + onValueChange = { text = it }, + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Sentences, + autoCorrect = false, + keyboardType = KeyboardType.Ascii, + ), + ) +} + +@Composable +fun TestFramework(){ + var searchText by remember { mutableStateOf("cats") } + val searchHistory = remember { mutableStateListOf() } - is MemoryPage -> { - MemoryScreen( - pictures = pictures, - memoryPage = page, - onSelectRelatedMemory = { pictureIndex -> - navigationStack.push(MemoryPage(pictureIndex)) - }, - onBack = { resetNavigation -> - if (resetNavigation) { - selectedPictureIndex.value = 0 - navigationStack.reset() - } else { - navigationStack.back() - } - }, - onHeaderClick = { pictureIndex -> - navigationStack.push(FullScreenPage(pictureIndex)) - }, - ) - } - is CameraPage -> { - CameraScreen( - onBack = { resetSelectedPicture -> - if (resetSelectedPicture) { - selectedPictureIndex.value = 0 - } - navigationStack.back() - }, + Column(modifier = Modifier.padding(30.dp)) { + TextField( + modifier = Modifier.testTag("searchText"), + value = searchText, + onValueChange = { + searchText = it + } + ) + Button( + modifier = Modifier.testTag("search"), + onClick = { + searchHistory.add("You searched for: $searchText") + } + ) { + Text("Search") + } + LazyColumn { + items(searchHistory) { + Text( + text = it, + fontSize = 20.sp, + modifier = Modifier.padding(start = 10.dp).testTag("attempt") ) } } } -} +} \ No newline at end of file diff --git a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/ImageViewer.ios.kt b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/ImageViewer.ios.kt index 1f40b9740a..ab32932f1f 100755 --- a/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/ImageViewer.ios.kt +++ b/examples/imageviewer/shared/src/iosMain/kotlin/example/imageviewer/ImageViewer.ios.kt @@ -27,15 +27,13 @@ internal fun ImageViewerIos() { getDependencies(ioScope, toastState) } - ImageViewerTheme { - Surface( - modifier = Modifier.fillMaxSize() - ) { - ImageViewerCommon( - dependencies = dependencies - ) - Toast(toastState) - } + Surface( + modifier = Modifier.fillMaxSize() + ) { + ImageViewerCommon( + dependencies = dependencies + ) + Toast(toastState) } }