You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
4.6 KiB
123 lines
4.6 KiB
package example.imageviewer.view |
|
|
|
import androidx.compose.foundation.layout.fillMaxSize |
|
import androidx.compose.material.Surface |
|
import androidx.compose.runtime.* |
|
import androidx.compose.ui.Alignment |
|
import androidx.compose.ui.Modifier |
|
import androidx.compose.ui.input.key.Key |
|
import androidx.compose.ui.input.key.KeyEventType |
|
import androidx.compose.ui.input.key.key |
|
import androidx.compose.ui.input.key.type |
|
import androidx.compose.ui.unit.DpSize |
|
import androidx.compose.ui.unit.dp |
|
import androidx.compose.ui.window.ApplicationScope |
|
import androidx.compose.ui.window.Window |
|
import androidx.compose.ui.window.WindowPosition |
|
import androidx.compose.ui.window.WindowState |
|
import example.imageviewer.* |
|
import example.imageviewer.filter.PlatformContext |
|
import example.imageviewer.model.PictureData |
|
import example.imageviewer.style.ImageViewerTheme |
|
import imageviewer.shared.generated.resources.Res |
|
import imageviewer.shared.generated.resources.ic_imageviewer_round |
|
import kotlinx.coroutines.CoroutineScope |
|
import kotlinx.coroutines.channels.BufferOverflow |
|
import kotlinx.coroutines.flow.MutableSharedFlow |
|
import kotlinx.coroutines.flow.SharedFlow |
|
import kotlinx.coroutines.flow.asSharedFlow |
|
import org.jetbrains.compose.resources.painterResource |
|
import java.awt.Dimension |
|
import java.awt.Toolkit |
|
|
|
class ExternalNavigationEventBus { |
|
private val _events = MutableSharedFlow<ExternalImageViewerEvent>( |
|
replay = 0, |
|
onBufferOverflow = BufferOverflow.DROP_OLDEST, |
|
extraBufferCapacity = 1, |
|
) |
|
val events = _events.asSharedFlow() |
|
|
|
fun produceEvent(event: ExternalImageViewerEvent) { |
|
_events.tryEmit(event) |
|
} |
|
} |
|
|
|
@Composable |
|
fun ApplicationScope.ImageViewerDesktop() { |
|
val ioScope = rememberCoroutineScope { ioDispatcher } |
|
val toastState = remember { mutableStateOf<ToastState>(ToastState.Hidden) } |
|
val externalNavigationEventBus = remember { ExternalNavigationEventBus() } |
|
val dependencies = remember { |
|
getDependencies(toastState, ioScope, externalNavigationEventBus.events) |
|
} |
|
|
|
Window( |
|
onCloseRequest = ::exitApplication, |
|
title = "Image Viewer", |
|
state = WindowState( |
|
position = WindowPosition.Aligned(Alignment.Center), |
|
size = getPreferredWindowSize(720, 857) |
|
), |
|
icon = painterResource(Res.drawable.ic_imageviewer_round), |
|
// https://github.com/JetBrains/compose-jb/issues/2741 |
|
onKeyEvent = { |
|
if (it.type == KeyEventType.KeyUp) { |
|
when (it.key) { |
|
Key.DirectionLeft -> externalNavigationEventBus.produceEvent( |
|
ExternalImageViewerEvent.Previous |
|
) |
|
|
|
Key.DirectionRight -> externalNavigationEventBus.produceEvent( |
|
ExternalImageViewerEvent.Next |
|
) |
|
|
|
Key.Escape -> externalNavigationEventBus.produceEvent( |
|
ExternalImageViewerEvent.ReturnBack |
|
) |
|
} |
|
} |
|
false |
|
} |
|
) { |
|
ImageViewerTheme { |
|
Surface( |
|
modifier = Modifier.fillMaxSize() |
|
) { |
|
ImageViewerCommon( |
|
dependencies = dependencies |
|
) |
|
Toast(toastState) |
|
} |
|
} |
|
} |
|
} |
|
|
|
private fun getDependencies( |
|
toastState: MutableState<ToastState>, |
|
ioScope: CoroutineScope, |
|
events: SharedFlow<ExternalImageViewerEvent> |
|
) = |
|
object : Dependencies() { |
|
override val notification: Notification = object : PopupNotification(localization) { |
|
override fun showPopUpMessage(text: String) { |
|
toastState.value = ToastState.Shown(text) |
|
} |
|
} |
|
override val imageStorage: DesktopImageStorage = DesktopImageStorage(pictures, ioScope) |
|
override val sharePicture: SharePicture = object : SharePicture { |
|
override fun share(context: PlatformContext, picture: PictureData) { |
|
// On Desktop share feature not supported |
|
} |
|
} |
|
override val externalEvents = events |
|
} |
|
|
|
private fun getPreferredWindowSize(desiredWidth: Int, desiredHeight: Int): DpSize { |
|
val screenSize: Dimension = Toolkit.getDefaultToolkit().screenSize |
|
val preferredWidth: Int = (screenSize.width * 0.8f).toInt() |
|
val preferredHeight: Int = (screenSize.height * 0.8f).toInt() |
|
val width: Int = if (desiredWidth < preferredWidth) desiredWidth else preferredWidth |
|
val height: Int = if (desiredHeight < preferredHeight) desiredHeight else preferredHeight |
|
return DpSize(width.dp, height.dp) |
|
}
|
|
|