diff --git a/ci/compose-uber-jar/gradle.properties b/ci/compose-uber-jar/gradle.properties index 03b9d463c9..e1ffd26e7f 100644 --- a/ci/compose-uber-jar/gradle.properties +++ b/ci/compose-uber-jar/gradle.properties @@ -1,2 +1,2 @@ -compose.version=1.1.0 +compose.version=1.2.0-beta01 kotlin.code.style=official diff --git a/components/gradle.properties b/components/gradle.properties index 8fb205f495..32b977f6ec 100644 --- a/components/gradle.properties +++ b/components/gradle.properties @@ -5,4 +5,4 @@ kotlin.code.style=official # __KOTLIN_COMPOSE_VERSION__ kotlin.version=1.6.10 # __LATEST_COMPOSE_RELEASE_VERSION__ -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/codeviewer/gradle.properties b/examples/codeviewer/gradle.properties index 6849fa0b48..0138e3e222 100644 --- a/examples/codeviewer/gradle.properties +++ b/examples/codeviewer/gradle.properties @@ -21,4 +21,4 @@ android.enableJetifier=true kotlin.code.style=official kotlin.version=1.6.10 agp.version=7.0.4 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/falling-balls/gradle.properties b/examples/falling-balls/gradle.properties index 9bb8d52f7d..b2088a7936 100644 --- a/examples/falling-balls/gradle.properties +++ b/examples/falling-balls/gradle.properties @@ -1,3 +1,3 @@ kotlin.code.style=official kotlin.version=1.6.10 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/imageviewer/gradle.properties b/examples/imageviewer/gradle.properties index 6849fa0b48..0138e3e222 100755 --- a/examples/imageviewer/gradle.properties +++ b/examples/imageviewer/gradle.properties @@ -21,4 +21,4 @@ android.enableJetifier=true kotlin.code.style=official kotlin.version=1.6.10 agp.version=7.0.4 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/intellij-plugin-with-experimental-shared-base/gradle.properties b/examples/intellij-plugin-with-experimental-shared-base/gradle.properties index bf812e078f..30ecbccfb6 100644 --- a/examples/intellij-plugin-with-experimental-shared-base/gradle.properties +++ b/examples/intellij-plugin-with-experimental-shared-base/gradle.properties @@ -1,5 +1,5 @@ kotlin.stdlib.default.dependency=false kotlin.code.style=official kotlin.version=1.6.10 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/intellij-plugin/gradle.properties b/examples/intellij-plugin/gradle.properties index 9bb8d52f7d..b2088a7936 100644 --- a/examples/intellij-plugin/gradle.properties +++ b/examples/intellij-plugin/gradle.properties @@ -1,3 +1,3 @@ kotlin.code.style=official kotlin.version=1.6.10 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/issues/gradle.properties b/examples/issues/gradle.properties index 242c14d70f..085bd89169 100644 --- a/examples/issues/gradle.properties +++ b/examples/issues/gradle.properties @@ -21,4 +21,4 @@ android.useAndroidX=true android.enableJetifier=true kotlin.version=1.6.10 agp.version=7.0.4 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/notepad/gradle.properties b/examples/notepad/gradle.properties index 654c3e3d5f..69de234bdd 100644 --- a/examples/notepad/gradle.properties +++ b/examples/notepad/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 kotlin.code.style=official kotlin.version=1.6.10 -compose.version=1.1.0 \ No newline at end of file +compose.version=1.2.0-beta01 \ No newline at end of file diff --git a/examples/todoapp-lite/gradle.properties b/examples/todoapp-lite/gradle.properties index 6849fa0b48..0138e3e222 100755 --- a/examples/todoapp-lite/gradle.properties +++ b/examples/todoapp-lite/gradle.properties @@ -21,4 +21,4 @@ android.enableJetifier=true kotlin.code.style=official kotlin.version=1.6.10 agp.version=7.0.4 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/todoapp/gradle.properties b/examples/todoapp/gradle.properties index b8b81092a6..8cbedcaab2 100755 --- a/examples/todoapp/gradle.properties +++ b/examples/todoapp/gradle.properties @@ -25,4 +25,4 @@ kotlin.native.disableCompilerDaemon=true #todo remove -Pkotlin.version=1.6.20 from Xcode project, when stable version on Compose with Koltin 1.6.20 or later released kotlin.version=1.6.10 -compose.version=1.1.0 \ No newline at end of file +compose.version=1.2.0-beta01 \ No newline at end of file diff --git a/examples/visual-effects/gradle.properties b/examples/visual-effects/gradle.properties index 9bb8d52f7d..b2088a7936 100644 --- a/examples/visual-effects/gradle.properties +++ b/examples/visual-effects/gradle.properties @@ -1,3 +1,3 @@ kotlin.code.style=official kotlin.version=1.6.10 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/web-compose-bird/gradle.properties b/examples/web-compose-bird/gradle.properties index 2e1d6a4d40..34ea8f9ae0 100644 --- a/examples/web-compose-bird/gradle.properties +++ b/examples/web-compose-bird/gradle.properties @@ -1,4 +1,4 @@ kotlin.code.style=official org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 kotlin.version=1.6.10 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/web-landing/gradle.properties b/examples/web-landing/gradle.properties index 9bb8d52f7d..b2088a7936 100644 --- a/examples/web-landing/gradle.properties +++ b/examples/web-landing/gradle.properties @@ -1,3 +1,3 @@ kotlin.code.style=official kotlin.version=1.6.10 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/web-with-react/gradle.properties b/examples/web-with-react/gradle.properties index 9bb8d52f7d..b2088a7936 100644 --- a/examples/web-with-react/gradle.properties +++ b/examples/web-with-react/gradle.properties @@ -1,3 +1,3 @@ kotlin.code.style=official kotlin.version=1.6.10 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/examples/widgets-gallery/gradle.properties b/examples/widgets-gallery/gradle.properties index a960629879..83dde7351b 100644 --- a/examples/widgets-gallery/gradle.properties +++ b/examples/widgets-gallery/gradle.properties @@ -20,5 +20,5 @@ android.enableJetifier=true # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official kotlin.version=1.6.10 -compose.version=1.1.0 +compose.version=1.2.0-beta01 agp.version=7.0.4 diff --git a/gradle-plugins/gradle.properties b/gradle-plugins/gradle.properties index 4ecce17018..0bdfa2f2af 100644 --- a/gradle-plugins/gradle.properties +++ b/gradle-plugins/gradle.properties @@ -6,7 +6,7 @@ kotlin.code.style=official # unless overridden by COMPOSE_GRADLE_PLUGIN_COMPOSE_VERSION env var. # # __LATEST_COMPOSE_RELEASE_VERSION__ -compose.version=1.2.0-alpha01-dev774 +compose.version=1.2.0-beta01 compose.compiler.version=1.3.0-alpha01 diff --git a/templates/desktop-template/gradle.properties b/templates/desktop-template/gradle.properties index 5679ab5bab..ebf7b99bee 100644 --- a/templates/desktop-template/gradle.properties +++ b/templates/desktop-template/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 kotlin.code.style=official kotlin.version=1.6.10 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/templates/multiplatform-template/gradle.properties b/templates/multiplatform-template/gradle.properties index c0554eeeca..eebc300cba 100644 --- a/templates/multiplatform-template/gradle.properties +++ b/templates/multiplatform-template/gradle.properties @@ -4,4 +4,4 @@ android.enableJetifier=true kotlin.code.style=official kotlin.version=1.6.10 agp.version=7.0.4 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/templates/web-template/gradle.properties b/templates/web-template/gradle.properties index 5679ab5bab..ebf7b99bee 100644 --- a/templates/web-template/gradle.properties +++ b/templates/web-template/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 kotlin.code.style=official kotlin.version=1.6.10 -compose.version=1.1.0 +compose.version=1.2.0-beta01 diff --git a/tools/replace.sh b/tools/replaceVersion.sh old mode 100755 new mode 100644 similarity index 100% rename from tools/replace.sh rename to tools/replaceVersion.sh diff --git a/tutorials/Getting_Started/README.md b/tutorials/Getting_Started/README.md index 7657d5f426..88b9f02621 100644 --- a/tutorials/Getting_Started/README.md +++ b/tutorials/Getting_Started/README.md @@ -45,7 +45,7 @@ For the latest versions, see the [latest versions](https://github.com/JetBrains/ ``` plugins { kotlin("jvm") version "1.6.10" - id("org.jetbrains.compose") version "1.1.0" + id("org.jetbrains.compose") version "1.2.0-beta01" } ``` @@ -81,7 +81,7 @@ import org.jetbrains.compose.compose plugins { kotlin("jvm") version "1.6.10" - id("org.jetbrains.compose") version "1.1.0" + id("org.jetbrains.compose") version "1.2.0-beta01" } repositories { diff --git a/tutorials/Image_And_Icons_Manipulations/README.md b/tutorials/Image_And_Icons_Manipulations/README.md index 653db7a3e0..227fa791b9 100755 --- a/tutorials/Image_And_Icons_Manipulations/README.md +++ b/tutorials/Image_And_Icons_Manipulations/README.md @@ -1,313 +1,313 @@ -# Image and in-app icons manipulations - -## What is covered - -In this tutorial we will show you how to work with images using Compose for Desktop. - -## Loading images from resources - -Using images from application resources is very simple. Suppose we have a PNG image that is placed in the `resources` directory in our project. For this tutorial we will use the image sample: - -Sample - -```kotlin -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.window.singleWindowApplication - -fun main() = singleWindowApplication { - Image( - painter = painterResource("sample.png"), - contentDescription = "Sample", - modifier = Modifier.fillMaxSize() - ) -} -``` - -`painterResource` supports raster (BMP, GIF, HEIF, ICO, JPEG, PNG, WBMP, WebP) and vector formats (SVG, [XML vector drawable](https://developer.android.com/guide/topics/graphics/vector-drawable-resources)). - -Resources - -## Loading images from device storage or network asynchronously - -To load an image stored in the device memory (or from network) you can use `loadImageBitmap`, `loadSvgPainter` or `loadXmlImageVector`. The example below shows how to use them to load an image asynchronously. - -```kotlin -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.width -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.produceState -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.painter.BitmapPainter -import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.graphics.vector.rememberVectorPainter -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.loadImageBitmap -import androidx.compose.ui.res.loadSvgPainter -import androidx.compose.ui.res.loadXmlImageVector -import androidx.compose.ui.unit.Density -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.singleWindowApplication -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import org.xml.sax.InputSource -import java.io.File -import java.io.IOException -import java.net.URL - -fun main() = singleWindowApplication { - val density = LocalDensity.current - Column { - AsyncImage( - load = { loadImageBitmap(File("sample.png")) }, - painterFor = { remember { BitmapPainter(it) } }, - contentDescription = "Sample", - modifier = Modifier.width(200.dp) - ) - AsyncImage( - load = { loadSvgPainter("https://github.com/JetBrains/compose-jb/raw/master/artwork/idea-logo.svg", density) }, - painterFor = { it }, - contentDescription = "Idea logo", - contentScale = ContentScale.FillWidth, - modifier = Modifier.width(200.dp) - ) - AsyncImage( - load = { loadXmlImageVector(File("compose-logo.xml"), density) }, - painterFor = { rememberVectorPainter(it) }, - contentDescription = "Compose logo", - contentScale = ContentScale.FillWidth, - modifier = Modifier.width(200.dp) - ) - } -} - -@Composable -fun AsyncImage( - load: suspend () -> T, - painterFor: @Composable (T) -> Painter, - contentDescription: String, - modifier: Modifier = Modifier, - contentScale: ContentScale = ContentScale.Fit, -) { - val image: T? by produceState(null) { - value = withContext(Dispatchers.IO) { - try { - load() - } catch (e: IOException) { - // instead of printing to console, you can also write this to log, - // or show some error placeholder - e.printStackTrace() - null - } - } - } - - if (image != null) { - Image( - painter = painterFor(image!!), - contentDescription = contentDescription, - contentScale = contentScale, - modifier = modifier - ) - } -} - -/* Loading from file with java.io API */ - -fun loadImageBitmap(file: File): ImageBitmap = - file.inputStream().buffered().use(::loadImageBitmap) - -fun loadSvgPainter(file: File, density: Density): Painter = - file.inputStream().buffered().use { loadSvgPainter(it, density) } - -fun loadXmlImageVector(file: File, density: Density): ImageVector = - file.inputStream().buffered().use { loadXmlImageVector(InputSource(it), density) } - -/* Loading from network with java.net API */ - -fun loadImageBitmap(url: String): ImageBitmap = - URL(url).openStream().buffered().use(::loadImageBitmap) - -fun loadSvgPainter(url: String, density: Density): Painter = - URL(url).openStream().buffered().use { loadSvgPainter(it, density) } - -fun loadXmlImageVector(url: String, density: Density): ImageVector = - URL(url).openStream().buffered().use { loadXmlImageVector(InputSource(it), density) } - -/* Loading from network with Ktor client API (https://ktor.io/docs/client.html). */ - -/* - -suspend fun loadImageBitmap(url: String): ImageBitmap = - urlStream(url).use(::loadImageBitmap) - -suspend fun loadSvgPainter(url: String, density: Density): Painter = - urlStream(url).use { loadSvgPainter(it, density) } - -suspend fun loadXmlImageVector(url: String, density: Density): ImageVector = - urlStream(url).use { loadXmlImageVector(InputSource(it), density) } - -@OptIn(KtorExperimentalAPI::class) -private suspend fun urlStream(url: String) = HttpClient(CIO).use { - ByteArrayInputStream(it.get(url)) -} - - */ -``` - -Storage - -[PNG](sample.png) - -[SVG](../../artwork/idea-logo.svg) - -[XML vector drawable](../../artwork/compose-logo.xml) - -## Drawing images using Canvas -```kotlin -import androidx.compose.foundation.Canvas -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.Paint -import androidx.compose.ui.graphics.drawscope.drawIntoCanvas -import androidx.compose.ui.graphics.vector.rememberVectorPainter -import androidx.compose.ui.graphics.withSave -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.loadImageBitmap -import androidx.compose.ui.res.loadSvgPainter -import androidx.compose.ui.res.loadXmlImageVector -import androidx.compose.ui.res.useResource -import androidx.compose.ui.window.singleWindowApplication -import org.xml.sax.InputSource - -fun main() = singleWindowApplication { - val density = LocalDensity.current // to calculate the intrinsic size of vector images (SVG, XML) - - val sample = remember { - useResource("sample.png", ::loadImageBitmap) - } - val ideaLogo = remember { - useResource("idea-logo.svg") { loadSvgPainter(it, density) } - } - val composeLogo = rememberVectorPainter( - remember { - useResource("compose-logo.xml") { loadXmlImageVector(InputSource(it), density) } - } - ) - - Canvas( - modifier = Modifier.fillMaxSize() - ) { - drawIntoCanvas { canvas -> - canvas.withSave { - canvas.drawImage(sample, Offset.Zero, Paint()) - canvas.translate(sample.width.toFloat(), 0f) - with(ideaLogo) { - draw(ideaLogo.intrinsicSize) - } - canvas.translate(ideaLogo.intrinsicSize.width, 0f) - with(composeLogo) { - draw(Size(100f, 100f)) - } - } - } - } -} -``` - -[PNG](sample.png) - -[SVG](../../artwork/idea-logo.svg) - -[XML vector drawable](../../artwork/compose-logo.xml) - -## Setting the application window icon - -You can set the icon for the window via parameter in the `Window` function. - -Note that to change the icon on the taskbar on some OS (macOs), you should change icon in [build.gradle](/tutorials/Native_distributions_and_local_execution#app-icon) - -```kotlin -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.paint -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.window.Window -import androidx.compose.ui.window.application - -fun main() = application { - val icon = painterResource("sample.png") - Window( - onCloseRequest = ::exitApplication, - icon = icon - ) { - Box(Modifier.paint(icon).fillMaxSize()) - } -} -``` - -Window icon - -In case of `singleWindowApplication` usage, you can use the following approach: - -```kotlin -import androidx.compose.material.Text -import androidx.compose.ui.graphics.painter.BitmapPainter -import androidx.compose.ui.res.loadImageBitmap -import androidx.compose.ui.res.useResource -import androidx.compose.ui.window.singleWindowApplication - -fun main() { - val icon = BitmapPainter(useResource("sample.png", ::loadImageBitmap)) - singleWindowApplication(icon = icon) { - Text("Hello World!") - } -} -``` - -## Setting the application tray icon - -You can create a tray icon for your application: - -```kotlin -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.window.Tray -import androidx.compose.ui.window.Window -import androidx.compose.ui.window.application - -fun main() = application { - val icon = painterResource("sample.png") - - Tray( - icon = icon, - menu = { - Item("Quit App", onClick = ::exitApplication) - } - ) - - Window(onCloseRequest = ::exitApplication, icon = icon) { - Image( - painter = icon, - contentDescription = "Icon", - modifier = Modifier.fillMaxSize() - ) - } -} -``` - -Tray icon +# Image and in-app icons manipulations + +## What is covered + +In this tutorial we will show you how to work with images using Compose for Desktop. + +## Loading images from resources + +Using images from application resources is very simple. Suppose we have a PNG image that is placed in the `resources` directory in our project. For this tutorial we will use the image sample: + +Sample + +```kotlin +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.window.singleWindowApplication + +fun main() = singleWindowApplication { + Image( + painter = painterResource("sample.png"), + contentDescription = "Sample", + modifier = Modifier.fillMaxSize() + ) +} +``` + +`painterResource` supports raster (BMP, GIF, HEIF, ICO, JPEG, PNG, WBMP, WebP) and vector formats (SVG, [XML vector drawable](https://developer.android.com/guide/topics/graphics/vector-drawable-resources)). + +Resources + +## Loading images from device storage or network asynchronously + +To load an image stored in the device memory (or from network) you can use `loadImageBitmap`, `loadSvgPainter` or `loadXmlImageVector`. The example below shows how to use them to load an image asynchronously. + +```kotlin +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.produceState +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.loadImageBitmap +import androidx.compose.ui.res.loadSvgPainter +import androidx.compose.ui.res.loadXmlImageVector +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.singleWindowApplication +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.xml.sax.InputSource +import java.io.File +import java.io.IOException +import java.net.URL + +fun main() = singleWindowApplication { + val density = LocalDensity.current + Column { + AsyncImage( + load = { loadImageBitmap(File("sample.png")) }, + painterFor = { remember { BitmapPainter(it) } }, + contentDescription = "Sample", + modifier = Modifier.width(200.dp) + ) + AsyncImage( + load = { loadSvgPainter("https://github.com/JetBrains/compose-jb/raw/master/artwork/idea-logo.svg", density) }, + painterFor = { it }, + contentDescription = "Idea logo", + contentScale = ContentScale.FillWidth, + modifier = Modifier.width(200.dp) + ) + AsyncImage( + load = { loadXmlImageVector(File("compose-logo.xml"), density) }, + painterFor = { rememberVectorPainter(it) }, + contentDescription = "Compose logo", + contentScale = ContentScale.FillWidth, + modifier = Modifier.width(200.dp) + ) + } +} + +@Composable +fun AsyncImage( + load: suspend () -> T, + painterFor: @Composable (T) -> Painter, + contentDescription: String, + modifier: Modifier = Modifier, + contentScale: ContentScale = ContentScale.Fit, +) { + val image: T? by produceState(null) { + value = withContext(Dispatchers.IO) { + try { + load() + } catch (e: IOException) { + // instead of printing to console, you can also write this to log, + // or show some error placeholder + e.printStackTrace() + null + } + } + } + + if (image != null) { + Image( + painter = painterFor(image!!), + contentDescription = contentDescription, + contentScale = contentScale, + modifier = modifier + ) + } +} + +/* Loading from file with java.io API */ + +fun loadImageBitmap(file: File): ImageBitmap = + file.inputStream().buffered().use(::loadImageBitmap) + +fun loadSvgPainter(file: File, density: Density): Painter = + file.inputStream().buffered().use { loadSvgPainter(it, density) } + +fun loadXmlImageVector(file: File, density: Density): ImageVector = + file.inputStream().buffered().use { loadXmlImageVector(InputSource(it), density) } + +/* Loading from network with java.net API */ + +fun loadImageBitmap(url: String): ImageBitmap = + URL(url).openStream().buffered().use(::loadImageBitmap) + +fun loadSvgPainter(url: String, density: Density): Painter = + URL(url).openStream().buffered().use { loadSvgPainter(it, density) } + +fun loadXmlImageVector(url: String, density: Density): ImageVector = + URL(url).openStream().buffered().use { loadXmlImageVector(InputSource(it), density) } + +/* Loading from network with Ktor client API (https://ktor.io/docs/client.html). */ + +/* + +suspend fun loadImageBitmap(url: String): ImageBitmap = + urlStream(url).use(::loadImageBitmap) + +suspend fun loadSvgPainter(url: String, density: Density): Painter = + urlStream(url).use { loadSvgPainter(it, density) } + +suspend fun loadXmlImageVector(url: String, density: Density): ImageVector = + urlStream(url).use { loadXmlImageVector(InputSource(it), density) } + +@OptIn(KtorExperimentalAPI::class) +private suspend fun urlStream(url: String) = HttpClient(CIO).use { + ByteArrayInputStream(it.get(url)) +} + + */ +``` + +Storage + +[PNG](sample.png) + +[SVG](../../artwork/idea-logo.svg) + +[XML vector drawable](../../artwork/compose-logo.xml) + +## Drawing images using Canvas +```kotlin +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Paint +import androidx.compose.ui.graphics.drawscope.drawIntoCanvas +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.graphics.withSave +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.loadImageBitmap +import androidx.compose.ui.res.loadSvgPainter +import androidx.compose.ui.res.loadXmlImageVector +import androidx.compose.ui.res.useResource +import androidx.compose.ui.window.singleWindowApplication +import org.xml.sax.InputSource + +fun main() = singleWindowApplication { + val density = LocalDensity.current // to calculate the intrinsic size of vector images (SVG, XML) + + val sample = remember { + useResource("sample.png", ::loadImageBitmap) + } + val ideaLogo = remember { + useResource("idea-logo.svg") { loadSvgPainter(it, density) } + } + val composeLogo = rememberVectorPainter( + remember { + useResource("compose-logo.xml") { loadXmlImageVector(InputSource(it), density) } + } + ) + + Canvas( + modifier = Modifier.fillMaxSize() + ) { + drawIntoCanvas { canvas -> + canvas.withSave { + canvas.drawImage(sample, Offset.Zero, Paint()) + canvas.translate(sample.width.toFloat(), 0f) + with(ideaLogo) { + draw(ideaLogo.intrinsicSize) + } + canvas.translate(ideaLogo.intrinsicSize.width, 0f) + with(composeLogo) { + draw(Size(100f, 100f)) + } + } + } + } +} +``` + +[PNG](sample.png) + +[SVG](../../artwork/idea-logo.svg) + +[XML vector drawable](../../artwork/compose-logo.xml) + +## Setting the application window icon + +You can set the icon for the window via parameter in the `Window` function. + +Note that to change the icon on the taskbar on some OS (macOs), you should change icon in [build.gradle](/tutorials/Native_distributions_and_local_execution#app-icon) + +```kotlin +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.paint +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.window.Window +import androidx.compose.ui.window.application + +fun main() = application { + val icon = painterResource("sample.png") + Window( + onCloseRequest = ::exitApplication, + icon = icon + ) { + Box(Modifier.paint(icon).fillMaxSize()) + } +} +``` + +Window icon + +In case of `singleWindowApplication` usage, you can use the following approach: + +```kotlin +import androidx.compose.material.Text +import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.compose.ui.res.loadImageBitmap +import androidx.compose.ui.res.useResource +import androidx.compose.ui.window.singleWindowApplication + +fun main() { + val icon = BitmapPainter(useResource("sample.png", ::loadImageBitmap)) + singleWindowApplication(icon = icon) { + Text("Hello World!") + } +} +``` + +## Setting the application tray icon + +You can create a tray icon for your application: + +```kotlin +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.window.Tray +import androidx.compose.ui.window.Window +import androidx.compose.ui.window.application + +fun main() = application { + val icon = painterResource("sample.png") + + Tray( + icon = icon, + menu = { + Item("Quit App", onClick = ::exitApplication) + } + ) + + Window(onCloseRequest = ::exitApplication, icon = icon) { + Image( + painter = icon, + contentDescription = "Icon", + modifier = Modifier.fillMaxSize() + ) + } +} +``` + +Tray icon diff --git a/tutorials/Web/Getting_Started/README.md b/tutorials/Web/Getting_Started/README.md index be90390b33..8ffba1bb35 100644 --- a/tutorials/Web/Getting_Started/README.md +++ b/tutorials/Web/Getting_Started/README.md @@ -39,7 +39,7 @@ pluginManagement { // Add compose gradle plugin plugins { kotlin("multiplatform") version "1.6.10" - id("org.jetbrains.compose") version "1.1.0" + id("org.jetbrains.compose") version "1.2.0-beta01" } // Add maven repositories diff --git a/web/gradle.properties b/web/gradle.properties index 18004c5d53..89ae2bff65 100644 --- a/web/gradle.properties +++ b/web/gradle.properties @@ -1,5 +1,5 @@ -COMPOSE_CORE_VERSION=1.1.0 -COMPOSE_WEB_VERSION=1.1.0 +COMPOSE_CORE_VERSION=1.2.0-beta01 +COMPOSE_WEB_VERSION=1.2.0-beta01 compose.web.buildSamples=false compose.web.tests.integration.withFirefox compose.web.tests.skip.benchmarks=false