Browse Source

Updated ImageViewer to 0.5.0-build270

pull/952/head
Roman Sedaikin 3 years ago
parent
commit
2e571c8734
  1. 14
      examples/imageviewer/build.gradle.kts
  2. 5
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/model/DesktopContentState.kt
  3. 44
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/style/Decoration.kt
  4. 158
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/utils/Application.kt
  5. 30
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/utils/GraphicsMath.kt
  6. 44
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/FullImageScreen.kt
  7. 7
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/MainScreen.kt
  8. 30
      examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/Zoomable.kt
  9. 39
      examples/imageviewer/desktop/src/jvmMain/kotlin/example/imageviewer/Main.kt

14
examples/imageviewer/build.gradle.kts

@ -1,27 +1,23 @@
buildscript { buildscript {
val composeVersion = System.getenv("COMPOSE_TEMPLATE_COMPOSE_VERSION") ?: "0.5.0-build270"
repositories { repositories {
mavenLocal().mavenContent {
includeModule("org.jetbrains.compose", "compose-gradle-plugin")
}
google() google()
mavenCentral() mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
} }
dependencies { dependencies {
// __LATEST_COMPOSE_RELEASE_VERSION__ classpath("org.jetbrains.compose:compose-gradle-plugin:$composeVersion")
classpath("org.jetbrains.compose:compose-gradle-plugin:0.4.0")
classpath("com.android.tools.build:gradle:4.0.1") classpath("com.android.tools.build:gradle:4.0.1")
// __KOTLIN_COMPOSE_VERSION__ classpath(kotlin("gradle-plugin", version = "1.5.21"))
classpath(kotlin("gradle-plugin", version = "1.5.10"))
} }
} }
allprojects { allprojects {
repositories { repositories {
mavenLocal()
google() google()
mavenCentral() mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
} }
} }

5
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/model/DesktopContentState.kt

@ -3,6 +3,7 @@ package example.imageviewer.model
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.RememberObserver import androidx.compose.runtime.RememberObserver
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.window.WindowState
import example.imageviewer.ResString import example.imageviewer.ResString
import example.imageviewer.core.FilterType import example.imageviewer.core.FilterType
import example.imageviewer.model.filtration.FiltersManager import example.imageviewer.model.filtration.FiltersManager
@ -19,10 +20,12 @@ import javax.swing.SwingUtilities.invokeLater
object ContentState : RememberObserver { object ContentState : RememberObserver {
lateinit var windowState: WindowState
private lateinit var repository: ImageRepository private lateinit var repository: ImageRepository
private lateinit var uriRepository: String private lateinit var uriRepository: String
fun applyContent(uriRepository: String): ContentState { fun applyContent(state: WindowState, uriRepository: String): ContentState {
windowState = state
if (this::uriRepository.isInitialized && this.uriRepository == uriRepository) { if (this::uriRepository.isInitialized && this.uriRepository == uriRepository) {
return this return this
} }

44
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/style/Decoration.kt

@ -1,58 +1,42 @@
package example.imageviewer.style package example.imageviewer.style
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.res.imageResource import androidx.compose.ui.res.painterResource
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import javax.imageio.ImageIO import javax.imageio.ImageIO
@Composable @Composable
fun icEmpty() = imageResource("images/empty.png") fun icEmpty() = painterResource("images/empty.png")
@Composable @Composable
fun icBack() = imageResource("images/back.png") fun icBack() = painterResource("images/back.png")
@Composable @Composable
fun icRefresh() = imageResource("images/refresh.png") fun icRefresh() = painterResource("images/refresh.png")
@Composable @Composable
fun icDots() = imageResource("images/dots.png") fun icDots() = painterResource("images/dots.png")
@Composable @Composable
fun icFilterGrayscaleOn() = imageResource("images/grayscale_on.png") fun icFilterGrayscaleOn() = painterResource("images/grayscale_on.png")
@Composable @Composable
fun icFilterGrayscaleOff() = imageResource("images/grayscale_off.png") fun icFilterGrayscaleOff() = painterResource("images/grayscale_off.png")
@Composable @Composable
fun icFilterPixelOn() = imageResource("images/pixel_on.png") fun icFilterPixelOn() = painterResource("images/pixel_on.png")
@Composable @Composable
fun icFilterPixelOff() = imageResource("images/pixel_off.png") fun icFilterPixelOff() = painterResource("images/pixel_off.png")
@Composable @Composable
fun icFilterBlurOn() = imageResource("images/blur_on.png") fun icFilterBlurOn() = painterResource("images/blur_on.png")
@Composable @Composable
fun icFilterBlurOff() = imageResource("images/blur_off.png") fun icFilterBlurOff() = painterResource("images/blur_off.png")
@Composable @Composable
fun icFilterUnknown() = imageResource("images/filter_unknown.png") fun icFilterUnknown() = painterResource("images/filter_unknown.png")
private var icon: BufferedImage? = null @Composable
fun icAppRounded(): BufferedImage { fun icAppRounded() = painterResource("images/ic_imageviewer_round.png")
if (icon != null) {
return icon!!
}
try {
val imageRes = "images/ic_imageviewer_round.png"
val img = Thread.currentThread().contextClassLoader.getResource(imageRes)
val bitmap: BufferedImage? = ImageIO.read(img)
if (bitmap != null) {
icon = bitmap
return bitmap
}
} catch (e: Exception) {
e.printStackTrace()
}
return BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)
}

158
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/utils/Application.kt

@ -1,158 +0,0 @@
package example.imageviewer.utils
import androidx.compose.desktop.AppManager
import androidx.compose.desktop.AppWindow
import androidx.compose.desktop.WindowEvents
import androidx.compose.runtime.*
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.window.v1.MenuBar
import kotlinx.coroutines.*
import kotlinx.coroutines.swing.Swing
import java.awt.image.BufferedImage
fun Application(
content: @Composable ApplicationScope.() -> Unit
) {
GlobalScope.launch(Dispatchers.Swing + ImmediateFrameClock()) {
AppManager.setEvents(onWindowsEmpty = null)
withRunningRecomposer { recomposer ->
val latch = CompletableDeferred<Unit>()
val applier = ApplicationApplier { latch.complete(Unit) }
val composition = Composition(applier, recomposer)
try {
val scope = ApplicationScope(recomposer)
composition.setContent { scope.content() }
latch.join()
} finally {
composition.dispose()
}
}
}
}
class ApplicationScope internal constructor(private val recomposer: Recomposer) {
@Composable
fun ComposableWindow(
title: String = "JetpackDesktopWindow",
size: IntSize = IntSize(800, 600),
location: IntOffset = IntOffset.Zero,
centered: Boolean = true,
icon: BufferedImage? = null,
menuBar: MenuBar? = null,
undecorated: Boolean = false,
resizable: Boolean = true,
events: WindowEvents = WindowEvents(),
onDismissRequest: (() -> Unit)? = null,
content: @Composable () -> Unit = {}
) {
var isOpened by remember { mutableStateOf(true) }
if (!isOpened) return
ComposeNode<AppWindow, ApplicationApplier>(
factory = {
val window = AppWindow(
title = title,
size = size,
location = location,
centered = centered,
icon = icon,
menuBar = menuBar,
undecorated = undecorated,
resizable = resizable,
events = events,
onDismissRequest = {
onDismissRequest?.invoke()
isOpened = false
}
)
window.show(recomposer, content)
window
},
update = {
set(title) { setTitle(it) }
set(size) { setSize(it.width, it.height) }
// set(location) { setLocation(it.x, it.y) }
set(icon) { setIcon(it) }
// set(menuBar) { if (it != null) setMenuBar(it) else removeMenuBar() }
// set(resizable) { setResizable(it) }
// set(events) { setEvents(it) }
// set(onDismissRequest) { setDismiss(it) }
}
)
}
}
private class ImmediateFrameClock : MonotonicFrameClock {
override suspend fun <R> withFrameNanos(
onFrame: (frameTimeNanos: Long) -> R
) = onFrame(System.nanoTime())
}
private class ApplicationApplier(
private val onWindowsEmpty: () -> Unit
) : Applier<AppWindow?> {
private val windows = mutableListOf<AppWindow>()
override var current: AppWindow? = null
override fun insertBottomUp(index: Int, instance: AppWindow?) {
requireNotNull(instance)
check(current == null) { "Windows cannot be nested!" }
windows.add(index, instance)
}
override fun remove(index: Int, count: Int) {
repeat(count) {
val window = windows.removeAt(index)
if (!window.isClosed) {
window.close()
}
}
}
override fun move(from: Int, to: Int, count: Int) {
if (from > to) {
var current = to
repeat(count) {
val node = windows.removeAt(from)
windows.add(current, node)
current++
}
} else {
repeat(count) {
val node = windows.removeAt(from)
windows.add(to - 1, node)
}
}
}
override fun clear() {
windows.forEach { if (!it.isClosed) it.close() }
windows.clear()
}
override fun onEndChanges() {
if (windows.isEmpty()) {
onWindowsEmpty()
}
}
override fun down(node: AppWindow?) {
requireNotNull(node)
check(current == null) { "Windows cannot be nested!" }
current = node
}
override fun up() {
check(current != null) { "Windows cannot be nested!" }
current = null
}
override fun insertTopDown(index: Int, instance: AppWindow?) {
// ignored. Building tree bottom-up
}
}

30
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/utils/GraphicsMath.kt

@ -1,7 +1,7 @@
package example.imageviewer.utils package example.imageviewer.utils
import androidx.compose.desktop.AppManager import androidx.compose.ui.window.WindowSize
import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp
import java.awt.Dimension import java.awt.Dimension
import java.awt.Graphics2D import java.awt.Graphics2D
import java.awt.Rectangle import java.awt.Rectangle
@ -38,10 +38,10 @@ fun scaleBitmapAspectRatio(
return result return result
} }
fun getDisplayBounds(bitmap: BufferedImage): Rectangle { fun getDisplayBounds(bitmap: BufferedImage, windowSize: WindowSize): Rectangle {
val boundW: Float = displayWidth().toFloat() val boundW: Float = windowSize.width.value.toFloat()
val boundH: Float = displayHeight().toFloat() val boundH: Float = windowSize.height.value.toFloat()
val ratioX: Float = bitmap.width / boundW val ratioX: Float = bitmap.width / boundW
val ratioY: Float = bitmap.height / boundH val ratioY: Float = bitmap.height / boundH
@ -108,22 +108,6 @@ fun applyBlurFilter(bitmap: BufferedImage): BufferedImage {
) )
} }
fun displayWidth(): Int {
val window = AppManager.focusedWindow
if (window != null) {
return window.width
}
return 0
}
fun displayHeight(): Int {
val window = AppManager.focusedWindow
if (window != null) {
return window.height
}
return 0
}
fun toByteArray(bitmap: BufferedImage) : ByteArray { fun toByteArray(bitmap: BufferedImage) : ByteArray {
val baos = ByteArrayOutputStream() val baos = ByteArrayOutputStream()
ImageIO.write(bitmap, "png", baos) ImageIO.write(bitmap, "png", baos)
@ -134,11 +118,11 @@ fun cropImage(bitmap: BufferedImage, crop: Rectangle) : BufferedImage {
return bitmap.getSubimage(crop.x, crop.y, crop.width, crop.height) return bitmap.getSubimage(crop.x, crop.y, crop.width, crop.height)
} }
fun getPreferredWindowSize(desiredWidth: Int, desiredHeight: Int): IntSize { fun getPreferredWindowSize(desiredWidth: Int, desiredHeight: Int): WindowSize {
val screenSize: Dimension = Toolkit.getDefaultToolkit().screenSize val screenSize: Dimension = Toolkit.getDefaultToolkit().screenSize
val preferredWidth: Int = (screenSize.width * 0.8f).toInt() val preferredWidth: Int = (screenSize.width * 0.8f).toInt()
val preferredHeight: Int = (screenSize.height * 0.8f).toInt() val preferredHeight: Int = (screenSize.height * 0.8f).toInt()
val width: Int = if (desiredWidth < preferredWidth) desiredWidth else preferredWidth val width: Int = if (desiredWidth < preferredWidth) desiredWidth else preferredWidth
val height: Int = if (desiredHeight < preferredHeight) desiredHeight else preferredHeight val height: Int = if (desiredHeight < preferredHeight) desiredHeight else preferredHeight
return IntSize(width, height) return WindowSize(width.dp, height.dp)
} }

44
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/FullImageScreen.kt

@ -25,13 +25,19 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.input.key.Key import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.shortcuts import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.type
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.WindowSize
import example.imageviewer.core.FilterType import example.imageviewer.core.FilterType
import example.imageviewer.model.AppState import example.imageviewer.model.AppState
import example.imageviewer.model.ContentState import example.imageviewer.model.ContentState
@ -50,11 +56,9 @@ import example.imageviewer.style.icFilterGrayscaleOn
import example.imageviewer.style.icFilterPixelOff import example.imageviewer.style.icFilterPixelOff
import example.imageviewer.style.icFilterPixelOn import example.imageviewer.style.icFilterPixelOn
import example.imageviewer.utils.cropImage import example.imageviewer.utils.cropImage
import example.imageviewer.utils.displayWidth
import example.imageviewer.utils.getDisplayBounds import example.imageviewer.utils.getDisplayBounds
import example.imageviewer.utils.toByteArray import example.imageviewer.utils.toByteArray
import java.awt.Rectangle import java.awt.Rectangle
import java.awt.event.KeyEvent
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import kotlin.math.pow import kotlin.math.pow
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -192,7 +196,7 @@ fun FilterButton(
} }
@Composable @Composable
fun getFilterImage(type: FilterType, content: ContentState): ImageBitmap { fun getFilterImage(type: FilterType, content: ContentState): Painter {
return when (type) { return when (type) {
FilterType.GrayScale -> if (content.isFilterEnabled(type)) icFilterGrayscaleOn() else icFilterGrayscaleOff() FilterType.GrayScale -> if (content.isFilterEnabled(type)) icFilterGrayscaleOn() else icFilterGrayscaleOff()
@ -201,6 +205,7 @@ fun getFilterImage(type: FilterType, content: ContentState): ImageBitmap {
} }
} }
@OptIn(ExperimentalComposeUiApi::class)
@Composable @Composable
fun setImage(content: ContentState) { fun setImage(content: ContentState) {
val drag = remember { DragHandler() } val drag = remember { DragHandler() }
@ -214,13 +219,14 @@ fun setImage(content: ContentState) {
Zoomable( Zoomable(
onScale = scale, onScale = scale,
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
.shortcuts { .onPreviewKeyEvent {
on(Key(KeyEvent.VK_LEFT)) { if (it.type == KeyEventType.KeyUp) {
content.swipePrevious() when (it.key) {
} Key.DirectionLeft -> content.swipePrevious()
on(Key(KeyEvent.VK_RIGHT)) { Key.DirectionRight -> content.swipeNext()
content.swipeNext() }
} }
false
} }
) { ) {
val bitmap = imageByGesture(content, scale, drag) val bitmap = imageByGesture(content, scale, drag)
@ -240,15 +246,20 @@ fun imageByGesture(
scale: ScaleHandler, scale: ScaleHandler,
drag: DragHandler drag: DragHandler
): ImageBitmap { ): ImageBitmap {
val bitmap = cropBitmapByScale(content.getSelectedImage(), scale.factor.value, drag) val bitmap = cropBitmapByScale(content.getSelectedImage(), content.windowState.size, scale.factor.value, drag)
return org.jetbrains.skija.Image.makeFromEncoded(toByteArray(bitmap)).asImageBitmap() return org.jetbrains.skija.Image.makeFromEncoded(toByteArray(bitmap)).asImageBitmap()
} }
private fun cropBitmapByScale(bitmap: BufferedImage, scale: Float, drag: DragHandler): BufferedImage { private fun cropBitmapByScale(
bitmap: BufferedImage,
size: WindowSize,
scale: Float,
drag: DragHandler
): BufferedImage {
val crop = cropBitmapByBounds( val crop = cropBitmapByBounds(
bitmap, bitmap,
getDisplayBounds(bitmap), getDisplayBounds(bitmap, size),
size,
scale, scale,
drag drag
) )
@ -261,6 +272,7 @@ private fun cropBitmapByScale(bitmap: BufferedImage, scale: Float, drag: DragHan
private fun cropBitmapByBounds( private fun cropBitmapByBounds(
bitmap: BufferedImage, bitmap: BufferedImage,
bounds: Rectangle, bounds: Rectangle,
size: WindowSize,
scaleFactor: Float, scaleFactor: Float,
drag: DragHandler drag: DragHandler
): Rectangle { ): Rectangle {
@ -274,7 +286,7 @@ private fun cropBitmapByBounds(
var boundW = (bounds.width / scale).roundToInt() var boundW = (bounds.width / scale).roundToInt()
var boundH = (bounds.height / scale).roundToInt() var boundH = (bounds.height / scale).roundToInt()
scale *= displayWidth() / bounds.width.toDouble() scale *= size.width.value / bounds.width.toDouble()
val offsetX = drag.getAmount().x / scale val offsetX = drag.getAmount().x / scale
val offsetY = drag.getAmount().y / scale val offsetY = drag.getAmount().y / scale

7
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/MainScreen.kt

@ -35,8 +35,9 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import example.imageviewer.ResString import example.imageviewer.ResString
@ -165,9 +166,9 @@ fun setPreviewImageUI(content: ContentState) {
Image( Image(
if (content.isMainImageEmpty()) if (content.isMainImageEmpty())
icEmpty() icEmpty()
else org.jetbrains.skija.Image.makeFromEncoded( else BitmapPainter(org.jetbrains.skija.Image.makeFromEncoded(
toByteArray(content.getSelectedImage()) toByteArray(content.getSelectedImage())
).asImageBitmap(), ).asImageBitmap()),
contentDescription = null, contentDescription = null,
modifier = Modifier modifier = Modifier
.fillMaxWidth().padding(start = 1.dp, top = 1.dp, end = 1.dp, bottom = 5.dp), .fillMaxWidth().padding(start = 1.dp, top = 1.dp, end = 1.dp, bottom = 5.dp),

30
examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/Zoomable.kt

@ -1,19 +1,24 @@
package example.imageviewer.view package example.imageviewer.view
import androidx.compose.foundation.focusable
import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.material.Surface import androidx.compose.material.Surface
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusModifier
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.input.key.Key import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.shortcuts import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.type
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.ExperimentalComposeUiApi
import example.imageviewer.style.Transparent import example.imageviewer.style.Transparent
import androidx.compose.runtime.DisposableEffect
@OptIn(ExperimentalComposeUiApi::class)
@Composable @Composable
fun Zoomable( fun Zoomable(
onScale: ScaleHandler, onScale: ScaleHandler,
@ -24,19 +29,18 @@ fun Zoomable(
Surface( Surface(
color = Transparent, color = Transparent,
modifier = modifier.shortcuts { modifier = modifier.onPreviewKeyEvent {
on(Key.I) { if (it.type == KeyEventType.KeyUp) {
onScale.onScale(1.2f) when (it.key) {
} Key.I -> onScale.onScale(1.2f)
on(Key.O) { Key.O -> onScale.onScale(0.8f)
onScale.onScale(0.8f) Key.R -> onScale.resetFactor()
} }
on(Key.R) {
onScale.resetFactor()
} }
false
} }
.focusRequester(focusRequester) .focusRequester(focusRequester)
.focusModifier() .focusable()
.pointerInput(Unit) { .pointerInput(Unit) {
detectTapGestures(onDoubleTap = { onScale.resetFactor() }) { detectTapGestures(onDoubleTap = { onScale.resetFactor() }) {
focusRequester.requestFocus() focusRequester.requestFocus()

39
examples/imageviewer/desktop/src/jvmMain/kotlin/example/imageviewer/Main.kt

@ -1,47 +1,58 @@
package example.imageviewer package example.imageviewer
import androidx.compose.desktop.DesktopTheme
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.WindowPosition
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState
import example.imageviewer.model.ContentState import example.imageviewer.model.ContentState
import example.imageviewer.style.icAppRounded import example.imageviewer.style.icAppRounded
import example.imageviewer.utils.Application
import example.imageviewer.utils.getPreferredWindowSize import example.imageviewer.utils.getPreferredWindowSize
import example.imageviewer.view.BuildAppUI import example.imageviewer.view.BuildAppUI
import example.imageviewer.view.SplashUI import example.imageviewer.view.SplashUI
fun main() = Application { fun main() = application {
val state = rememberWindowState()
val content = remember { val content = remember {
ContentState.applyContent( ContentState.applyContent(
state,
"https://raw.githubusercontent.com/JetBrains/compose-jb/master/artwork/imageviewerrepo/fetching.list" "https://raw.githubusercontent.com/JetBrains/compose-jb/master/artwork/imageviewerrepo/fetching.list"
) )
} }
val icon = remember(::icAppRounded) val icon = icAppRounded()
if (content.isAppReady()) { if (content.isAppReady()) {
ComposableWindow( Window(
onCloseRequest = ::exitApplication,
title = "Image Viewer", title = "Image Viewer",
size = getPreferredWindowSize(800, 1000), state = WindowState(
position = WindowPosition.Aligned(Alignment.Center),
size = getPreferredWindowSize(800, 1000)
),
icon = icon icon = icon
) { ) {
MaterialTheme { MaterialTheme {
DesktopTheme { BuildAppUI(content)
BuildAppUI(content)
}
} }
} }
} else { } else {
ComposableWindow( Window(
onCloseRequest = ::exitApplication,
title = "Image Viewer", title = "Image Viewer",
size = getPreferredWindowSize(800, 300), state = WindowState(
position = WindowPosition.Aligned(Alignment.Center),
size = getPreferredWindowSize(800, 300)
),
undecorated = true, undecorated = true,
icon = icon, icon = icon,
) { ) {
MaterialTheme { MaterialTheme {
DesktopTheme { SplashUI()
SplashUI()
}
} }
} }
} }

Loading…
Cancel
Save