CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-compose-desktop--desktop-jvm

Compose Multiplatform Desktop JVM support library for building cross-platform desktop applications with declarative UI framework based on Jetpack Compose

Pending
Overview
Eval results
Files

desktop-components.mddocs/

Desktop Components

Desktop components provide enhanced UI functionality specifically optimized for desktop platforms, including resizable panels, animated image support, and desktop-specific interactions.

SplitPane Component

The SplitPane component allows creating resizable panels with a draggable splitter.

Composable Functions

@ExperimentalSplitPaneApi
@Composable
fun HorizontalSplitPane(
    modifier: Modifier = Modifier,
    splitPaneState: SplitPaneState = rememberSplitPaneState(),
    content: SplitPaneScope.() -> Unit
)

@ExperimentalSplitPaneApi
@Composable
fun VerticalSplitPane(
    modifier: Modifier = Modifier,
    splitPaneState: SplitPaneState = rememberSplitPaneState(),
    content: SplitPaneScope.() -> Unit
)

SplitPane State

@Stable
class SplitPaneState {
    var positionPercentage: Float
    fun dispatchRawMovement(delta: Float): Float
}

@ExperimentalSplitPaneApi
@Composable
fun rememberSplitPaneState(
    initialPositionPercentage: Float = 0f,
    moveEnabled: Boolean = true
): SplitPaneState

SplitPane Scope

@ExperimentalSplitPaneApi
interface SplitPaneScope {
    fun first(
        minSize: Dp = 0.dp,
        content: @Composable () -> Unit
    )
    
    fun second(
        minSize: Dp = 0.dp,
        content: @Composable () -> Unit
    )
    
    fun splitter(block: SplitterScope.() -> Unit)
}

@ExperimentalSplitPaneApi
interface SplitterScope {
    fun visiblePart(content: @Composable () -> Unit)
    fun handle(
        alignment: SplitterHandleAlignment = SplitterHandleAlignment.ABOVE,
        content: @Composable HandleScope.() -> Unit
    )
}

@ExperimentalSplitPaneApi
interface HandleScope {
    fun Modifier.markAsHandle(): Modifier
}

Usage Example

import org.jetbrains.compose.splitpane.ExperimentalSplitPaneApi
import org.jetbrains.compose.splitpane.HorizontalSplitPane
import org.jetbrains.compose.splitpane.VerticalSplitPane
import org.jetbrains.compose.splitpane.rememberSplitPaneState

@OptIn(ExperimentalSplitPaneApi::class)
@Composable
fun SplitPaneExample() {
    val horizontalSplitState = rememberSplitPaneState(initialPositionPercentage = 0.3f)
    val verticalSplitState = rememberSplitPaneState(initialPositionPercentage = 0.7f)
    
    HorizontalSplitPane(
        splitPaneState = horizontalSplitState
    ) {
        first {
            // Left panel content
            Box(
                modifier = Modifier.fillMaxSize().background(Color.LightGray),
                contentAlignment = Alignment.Center
            ) {
                Text("Left Panel")
            }
        }
        second {
            VerticalSplitPane(
                splitPaneState = verticalSplitState
            ) {
                first {
                    // Top-right panel
                    Box(
                        modifier = Modifier.fillMaxSize().background(Color.Blue.copy(alpha = 0.3f)),
                        contentAlignment = Alignment.Center
                    ) {
                        Text("Top Right Panel")
                    }
                }
                second {
                    // Bottom-right panel
                    Box(
                        modifier = Modifier.fillMaxSize().background(Color.Green.copy(alpha = 0.3f)),
                        contentAlignment = Alignment.Center
                    ) {
                        Text("Bottom Right Panel")
                    }
                }
            }
        }
    }
}

AnimatedImage Component

The AnimatedImage component provides support for displaying animated images like GIFs.

Composable Functions

@Composable
fun AnimatedImage(
    animatedImageLoader: AnimatedImageLoader,
    modifier: Modifier = Modifier,
    contentDescription: String? = null,
    contentScale: ContentScale = ContentScale.Fit,
    alignment: Alignment = Alignment.Center,
    alpha: Float = DefaultAlpha,
    colorFilter: ColorFilter? = null
)

AnimatedImageLoader

interface AnimatedImageLoader {
    suspend fun load(): AnimatedImageLoadResult
}

sealed class AnimatedImageLoadResult {
    object Loading : AnimatedImageLoadResult()
    class Success(val image: AnimatedImage) : AnimatedImageLoadResult()
    class Error(val exception: Throwable) : AnimatedImageLoadResult()
}

abstract class AnimatedImage {
    abstract val frames: List<ImageBitmap>
    abstract val frameDelays: List<Int>
    abstract fun intrinsicSize(): IntSize
}

Image Loaders

class ResourceAnimatedImageLoader(
    resourcePath: String
) : AnimatedImageLoader

class NetworkAnimatedImageLoader(
    url: String,
    httpClient: HttpClient? = null
) : AnimatedImageLoader

@Composable
fun LocalAnimatedImageLoader.current: AnimatedImageLoader

Usage Example

import org.jetbrains.compose.animatedimage.AnimatedImage
import org.jetbrains.compose.animatedimage.ResourceAnimatedImageLoader
import org.jetbrains.compose.animatedimage.NetworkAnimatedImageLoader
import org.jetbrains.compose.animatedimage.LocalAnimatedImageLoader

@Composable
fun AnimatedImageExample() {
    Column {
        // Load from resources
        AnimatedImage(
            animatedImageLoader = ResourceAnimatedImageLoader("animations/loading.gif"),
            modifier = Modifier.size(100.dp),
            contentDescription = "Loading animation"
        )
        
        // Load from network
        AnimatedImage(
            animatedImageLoader = NetworkAnimatedImageLoader("https://example.com/animation.gif"),
            modifier = Modifier.size(200.dp),
            contentDescription = "Network animation",
            contentScale = ContentScale.Crop
        )
    }
}

// Providing a default loader
@Composable
fun MyApp() {
    CompositionLocalProvider(
        LocalAnimatedImageLoader provides ResourceAnimatedImageLoader("default.gif")
    ) {
        AnimatedImageExample()
    }
}

Resource Access

Desktop-specific resource loading utilities.

ResourceEnvironment

object ResourceEnvironment {
    fun isRunningFromJar(): Boolean
    fun getResourcePath(resourcePath: String): String?
}

ResourceReader

interface ResourceReader {
    suspend fun read(path: String): ByteArray
    suspend fun readText(path: String): String
}

object DesktopResourceReader : ResourceReader

Usage Example

import org.jetbrains.compose.resources.ResourceReader
import org.jetbrains.compose.resources.ResourceEnvironment

@Composable
fun ResourceExample() {
    var imageData by remember { mutableStateOf<ByteArray?>(null) }
    
    LaunchedEffect(Unit) {
        try {
            imageData = DesktopResourceReader.read("images/icon.png")
        } catch (e: Exception) {
            println("Failed to load resource: ${e.message}")
        }
    }
    
    imageData?.let { data ->
        // Use the image data
        Image(
            bitmap = org.jetbrains.skia.Image.makeFromEncoded(data).toComposeImageBitmap(),
            contentDescription = "App icon"
        )
    }
}

Component Dependencies

Add desktop components to your project:

dependencies {
    // SplitPane component (experimental)
    implementation(compose.desktop.components.splitPane)
    
    // AnimatedImage component (experimental) 
    implementation(compose.desktop.components.animatedImage)
    
    // Resources support
    implementation(compose.components.resources)
}

Browser Component (Experimental)

The Browser component provides embedded web browser functionality using CEF (Chromium Embedded Framework).

Browser Interface

interface Browser {
    fun load(url: String)
}

class BrowserView : Browser {
    override fun load(url: String)
    fun view(): ComposeWindow
    fun dismiss()
}

Usage Example

import org.jetbrains.compose.desktop.browser.BrowserView

@Composable
fun BrowserExample() {
    val browser = remember { BrowserView() }
    
    Column {
        Button(
            onClick = { browser.load("https://example.com") }
        ) {
            Text("Load Website")
        }
        
        Button(
            onClick = { browser.dismiss() }
        ) {
            Text("Close Browser")
        }
    }
}

VideoPlayer Component (Experimental)

The VideoPlayer component provides video playback functionality using VLC backend.

VideoPlayer Function

@Composable
fun VideoPlayerImpl(
    url: String,
    isResumed: Boolean = true,
    volume: Float = 1f,
    speed: Float = 1f,
    seek: Long = 0,
    isFullscreen: Boolean = false,
    onFinish: () -> Unit = {}
)

Usage Example

import org.jetbrains.compose.videoplayer.VideoPlayerImpl

@Composable
fun VideoPlayerExample() {
    var isPlaying by remember { mutableStateOf(true) }
    var volume by remember { mutableStateOf(1f) }
    
    Column {
        VideoPlayerImpl(
            url = "file:///path/to/video.mp4",
            isResumed = isPlaying,
            volume = volume,
            speed = 1f,
            onFinish = { println("Video finished playing") }
        )
        
        Row {
            Button(
                onClick = { isPlaying = !isPlaying }
            ) {
                Text(if (isPlaying) "Pause" else "Play")
            }
            
            Slider(
                value = volume,
                onValueChange = { volume = it },
                valueRange = 0f..1f
            )
        }
    }
}

Experimental API Notice

Desktop components are marked with @ExperimentalComposeLibrary annotation, indicating they are experimental and their API may change in future versions.

@OptIn(ExperimentalComposeLibrary::class)
@Composable 
fun MyDesktopApp() {
    // Use experimental components
}

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-compose-desktop--desktop-jvm

docs

desktop-application.md

desktop-components.md

gradle-plugin.md

index.md

resource-management.md

ui-tooling.md

tile.json