0
# Desktop Components
1
2
Desktop components provide enhanced UI functionality specifically optimized for desktop platforms, including resizable panels, animated image support, and desktop-specific interactions.
3
4
## SplitPane Component
5
6
The SplitPane component allows creating resizable panels with a draggable splitter.
7
8
### Composable Functions
9
10
```kotlin { .api }
11
@ExperimentalSplitPaneApi
12
@Composable
13
fun HorizontalSplitPane(
14
modifier: Modifier = Modifier,
15
splitPaneState: SplitPaneState = rememberSplitPaneState(),
16
content: SplitPaneScope.() -> Unit
17
)
18
19
@ExperimentalSplitPaneApi
20
@Composable
21
fun VerticalSplitPane(
22
modifier: Modifier = Modifier,
23
splitPaneState: SplitPaneState = rememberSplitPaneState(),
24
content: SplitPaneScope.() -> Unit
25
)
26
```
27
28
### SplitPane State
29
30
```kotlin { .api }
31
@Stable
32
class SplitPaneState {
33
var positionPercentage: Float
34
fun dispatchRawMovement(delta: Float): Float
35
}
36
37
@ExperimentalSplitPaneApi
38
@Composable
39
fun rememberSplitPaneState(
40
initialPositionPercentage: Float = 0f,
41
moveEnabled: Boolean = true
42
): SplitPaneState
43
```
44
45
### SplitPane Scope
46
47
```kotlin { .api }
48
@ExperimentalSplitPaneApi
49
interface SplitPaneScope {
50
fun first(
51
minSize: Dp = 0.dp,
52
content: @Composable () -> Unit
53
)
54
55
fun second(
56
minSize: Dp = 0.dp,
57
content: @Composable () -> Unit
58
)
59
60
fun splitter(block: SplitterScope.() -> Unit)
61
}
62
63
@ExperimentalSplitPaneApi
64
interface SplitterScope {
65
fun visiblePart(content: @Composable () -> Unit)
66
fun handle(
67
alignment: SplitterHandleAlignment = SplitterHandleAlignment.ABOVE,
68
content: @Composable HandleScope.() -> Unit
69
)
70
}
71
72
@ExperimentalSplitPaneApi
73
interface HandleScope {
74
fun Modifier.markAsHandle(): Modifier
75
}
76
```
77
78
### Usage Example
79
80
```kotlin
81
import org.jetbrains.compose.splitpane.ExperimentalSplitPaneApi
82
import org.jetbrains.compose.splitpane.HorizontalSplitPane
83
import org.jetbrains.compose.splitpane.VerticalSplitPane
84
import org.jetbrains.compose.splitpane.rememberSplitPaneState
85
86
@OptIn(ExperimentalSplitPaneApi::class)
87
@Composable
88
fun SplitPaneExample() {
89
val horizontalSplitState = rememberSplitPaneState(initialPositionPercentage = 0.3f)
90
val verticalSplitState = rememberSplitPaneState(initialPositionPercentage = 0.7f)
91
92
HorizontalSplitPane(
93
splitPaneState = horizontalSplitState
94
) {
95
first {
96
// Left panel content
97
Box(
98
modifier = Modifier.fillMaxSize().background(Color.LightGray),
99
contentAlignment = Alignment.Center
100
) {
101
Text("Left Panel")
102
}
103
}
104
second {
105
VerticalSplitPane(
106
splitPaneState = verticalSplitState
107
) {
108
first {
109
// Top-right panel
110
Box(
111
modifier = Modifier.fillMaxSize().background(Color.Blue.copy(alpha = 0.3f)),
112
contentAlignment = Alignment.Center
113
) {
114
Text("Top Right Panel")
115
}
116
}
117
second {
118
// Bottom-right panel
119
Box(
120
modifier = Modifier.fillMaxSize().background(Color.Green.copy(alpha = 0.3f)),
121
contentAlignment = Alignment.Center
122
) {
123
Text("Bottom Right Panel")
124
}
125
}
126
}
127
}
128
}
129
}
130
```
131
132
## AnimatedImage Component
133
134
The AnimatedImage component provides support for displaying animated images like GIFs.
135
136
### Composable Functions
137
138
```kotlin { .api }
139
@Composable
140
fun AnimatedImage(
141
animatedImageLoader: AnimatedImageLoader,
142
modifier: Modifier = Modifier,
143
contentDescription: String? = null,
144
contentScale: ContentScale = ContentScale.Fit,
145
alignment: Alignment = Alignment.Center,
146
alpha: Float = DefaultAlpha,
147
colorFilter: ColorFilter? = null
148
)
149
```
150
151
### AnimatedImageLoader
152
153
```kotlin { .api }
154
interface AnimatedImageLoader {
155
suspend fun load(): AnimatedImageLoadResult
156
}
157
158
sealed class AnimatedImageLoadResult {
159
object Loading : AnimatedImageLoadResult()
160
class Success(val image: AnimatedImage) : AnimatedImageLoadResult()
161
class Error(val exception: Throwable) : AnimatedImageLoadResult()
162
}
163
164
abstract class AnimatedImage {
165
abstract val frames: List<ImageBitmap>
166
abstract val frameDelays: List<Int>
167
abstract fun intrinsicSize(): IntSize
168
}
169
```
170
171
### Image Loaders
172
173
```kotlin { .api }
174
class ResourceAnimatedImageLoader(
175
resourcePath: String
176
) : AnimatedImageLoader
177
178
class NetworkAnimatedImageLoader(
179
url: String,
180
httpClient: HttpClient? = null
181
) : AnimatedImageLoader
182
183
@Composable
184
fun LocalAnimatedImageLoader.current: AnimatedImageLoader
185
```
186
187
### Usage Example
188
189
```kotlin
190
import org.jetbrains.compose.animatedimage.AnimatedImage
191
import org.jetbrains.compose.animatedimage.ResourceAnimatedImageLoader
192
import org.jetbrains.compose.animatedimage.NetworkAnimatedImageLoader
193
import org.jetbrains.compose.animatedimage.LocalAnimatedImageLoader
194
195
@Composable
196
fun AnimatedImageExample() {
197
Column {
198
// Load from resources
199
AnimatedImage(
200
animatedImageLoader = ResourceAnimatedImageLoader("animations/loading.gif"),
201
modifier = Modifier.size(100.dp),
202
contentDescription = "Loading animation"
203
)
204
205
// Load from network
206
AnimatedImage(
207
animatedImageLoader = NetworkAnimatedImageLoader("https://example.com/animation.gif"),
208
modifier = Modifier.size(200.dp),
209
contentDescription = "Network animation",
210
contentScale = ContentScale.Crop
211
)
212
}
213
}
214
215
// Providing a default loader
216
@Composable
217
fun MyApp() {
218
CompositionLocalProvider(
219
LocalAnimatedImageLoader provides ResourceAnimatedImageLoader("default.gif")
220
) {
221
AnimatedImageExample()
222
}
223
}
224
```
225
226
## Resource Access
227
228
Desktop-specific resource loading utilities.
229
230
### ResourceEnvironment
231
232
```kotlin { .api }
233
object ResourceEnvironment {
234
fun isRunningFromJar(): Boolean
235
fun getResourcePath(resourcePath: String): String?
236
}
237
```
238
239
### ResourceReader
240
241
```kotlin { .api }
242
interface ResourceReader {
243
suspend fun read(path: String): ByteArray
244
suspend fun readText(path: String): String
245
}
246
247
object DesktopResourceReader : ResourceReader
248
```
249
250
### Usage Example
251
252
```kotlin
253
import org.jetbrains.compose.resources.ResourceReader
254
import org.jetbrains.compose.resources.ResourceEnvironment
255
256
@Composable
257
fun ResourceExample() {
258
var imageData by remember { mutableStateOf<ByteArray?>(null) }
259
260
LaunchedEffect(Unit) {
261
try {
262
imageData = DesktopResourceReader.read("images/icon.png")
263
} catch (e: Exception) {
264
println("Failed to load resource: ${e.message}")
265
}
266
}
267
268
imageData?.let { data ->
269
// Use the image data
270
Image(
271
bitmap = org.jetbrains.skia.Image.makeFromEncoded(data).toComposeImageBitmap(),
272
contentDescription = "App icon"
273
)
274
}
275
}
276
```
277
278
## Component Dependencies
279
280
Add desktop components to your project:
281
282
```kotlin
283
dependencies {
284
// SplitPane component (experimental)
285
implementation(compose.desktop.components.splitPane)
286
287
// AnimatedImage component (experimental)
288
implementation(compose.desktop.components.animatedImage)
289
290
// Resources support
291
implementation(compose.components.resources)
292
}
293
```
294
295
## Browser Component (Experimental)
296
297
The Browser component provides embedded web browser functionality using CEF (Chromium Embedded Framework).
298
299
### Browser Interface
300
301
```kotlin { .api }
302
interface Browser {
303
fun load(url: String)
304
}
305
306
class BrowserView : Browser {
307
override fun load(url: String)
308
fun view(): ComposeWindow
309
fun dismiss()
310
}
311
```
312
313
### Usage Example
314
315
```kotlin
316
import org.jetbrains.compose.desktop.browser.BrowserView
317
318
@Composable
319
fun BrowserExample() {
320
val browser = remember { BrowserView() }
321
322
Column {
323
Button(
324
onClick = { browser.load("https://example.com") }
325
) {
326
Text("Load Website")
327
}
328
329
Button(
330
onClick = { browser.dismiss() }
331
) {
332
Text("Close Browser")
333
}
334
}
335
}
336
```
337
338
## VideoPlayer Component (Experimental)
339
340
The VideoPlayer component provides video playback functionality using VLC backend.
341
342
### VideoPlayer Function
343
344
```kotlin { .api }
345
@Composable
346
fun VideoPlayerImpl(
347
url: String,
348
isResumed: Boolean = true,
349
volume: Float = 1f,
350
speed: Float = 1f,
351
seek: Long = 0,
352
isFullscreen: Boolean = false,
353
onFinish: () -> Unit = {}
354
)
355
```
356
357
### Usage Example
358
359
```kotlin
360
import org.jetbrains.compose.videoplayer.VideoPlayerImpl
361
362
@Composable
363
fun VideoPlayerExample() {
364
var isPlaying by remember { mutableStateOf(true) }
365
var volume by remember { mutableStateOf(1f) }
366
367
Column {
368
VideoPlayerImpl(
369
url = "file:///path/to/video.mp4",
370
isResumed = isPlaying,
371
volume = volume,
372
speed = 1f,
373
onFinish = { println("Video finished playing") }
374
)
375
376
Row {
377
Button(
378
onClick = { isPlaying = !isPlaying }
379
) {
380
Text(if (isPlaying) "Pause" else "Play")
381
}
382
383
Slider(
384
value = volume,
385
onValueChange = { volume = it },
386
valueRange = 0f..1f
387
)
388
}
389
}
390
}
391
```
392
393
## Experimental API Notice
394
395
Desktop components are marked with `@ExperimentalComposeLibrary` annotation, indicating they are experimental and their API may change in future versions.
396
397
```kotlin
398
@OptIn(ExperimentalComposeLibrary::class)
399
@Composable
400
fun MyDesktopApp() {
401
// Use experimental components
402
}
403
```