init
This commit is contained in:
43
desktop/build.gradle.kts
Normal file
43
desktop/build.gradle.kts
Normal file
@ -0,0 +1,43 @@
|
||||
import org.jetbrains.compose.compose
|
||||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("org.jetbrains.compose")
|
||||
}
|
||||
|
||||
group = "com.eim"
|
||||
version = "1.0-SNAPSHOT"
|
||||
|
||||
|
||||
kotlin {
|
||||
jvm {
|
||||
compilations.all {
|
||||
kotlinOptions.jvmTarget = "17"
|
||||
}
|
||||
withJava()
|
||||
}
|
||||
sourceSets {
|
||||
val jvmMain by getting {
|
||||
dependencies {
|
||||
implementation(project(":common"))
|
||||
implementation(compose.desktop.currentOs)
|
||||
implementation(project(":window-styler"))
|
||||
}
|
||||
}
|
||||
val jvmTest by getting
|
||||
}
|
||||
}
|
||||
|
||||
compose.desktop {
|
||||
application {
|
||||
mainClass = "MainKt"
|
||||
nativeDistributions {
|
||||
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
||||
packageName = "eimusic"
|
||||
packageVersion = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
119
desktop/src/jvmMain/kotlin/Main.kt
Normal file
119
desktop/src/jvmMain/kotlin/Main.kt
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.*
|
||||
import com.eim.common.App
|
||||
import com.konyaco.fluent.*
|
||||
import com.konyaco.fluent.background.Layer
|
||||
import com.konyaco.fluent.component.Button
|
||||
import com.konyaco.fluent.component.Switcher
|
||||
import com.konyaco.fluent.component.Text
|
||||
import com.mayakapps.compose.windowstyler.WindowBackdrop
|
||||
import com.mayakapps.compose.windowstyler.WindowBackdropStyle
|
||||
import com.mayakapps.compose.windowstyler.WindowCornerPreference
|
||||
import com.mayakapps.compose.windowstyler.WindowFrameStyle
|
||||
import java.awt.Dimension
|
||||
|
||||
|
||||
val minimumWidth = 1024
|
||||
val minimumHeight = 768
|
||||
|
||||
fun WindowScope.setMinimumSize() {
|
||||
window.minimumSize = Dimension(minimumWidth, minimumHeight)
|
||||
}
|
||||
|
||||
|
||||
fun main() = application {
|
||||
val state =
|
||||
rememberWindowState(placement = WindowPlacement.Floating, width = minimumWidth.dp, height = minimumHeight.dp)
|
||||
var isVisible by remember { mutableStateOf(true) }
|
||||
var canResizeable by remember { mutableStateOf(true) }
|
||||
var systemColor by remember { mutableStateOf(Color(0xFF0078D4)) }
|
||||
Window(
|
||||
onCloseRequest = { isVisible = false },
|
||||
// undecorated = true,
|
||||
// transparent = true,
|
||||
state = state,
|
||||
visible = isVisible,
|
||||
resizable = canResizeable,
|
||||
title = WindowProperty.title,
|
||||
icon = TrayIcon
|
||||
) {
|
||||
val systemDarkMode = isSystemInDarkTheme()
|
||||
var darkMode by remember(systemDarkMode) { mutableStateOf(systemDarkMode) }
|
||||
|
||||
WindowBackdropStyle(
|
||||
isDarkTheme = darkMode,
|
||||
backdropType = WindowBackdrop.Acrylic(Color.Unspecified),
|
||||
frameStyle = WindowFrameStyle(
|
||||
cornerPreference = WindowCornerPreference.ROUNDED,
|
||||
),
|
||||
)
|
||||
|
||||
setMinimumSize()
|
||||
|
||||
FluentTheme(colors = if (darkMode) darkColors(systemColor) else lightColors(systemColor)) {
|
||||
val density = LocalDensity.current
|
||||
var scale by remember(density) { mutableStateOf(density.density) }
|
||||
|
||||
Row {
|
||||
Column {
|
||||
// AppWindowTitleBar(
|
||||
// state,
|
||||
// onClose = { isVisible = false },
|
||||
// onPlacementChange = { canResizeable = it })
|
||||
Controller(scale, { scale = it }, darkMode, { darkMode = it })
|
||||
App()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
AppTray({ isVisible = true })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Controller(
|
||||
scale: Float,
|
||||
onScaleChange: (Float) -> Unit,
|
||||
darkMode: Boolean,
|
||||
onDarkModeChange: (Boolean) -> Unit
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
val density = LocalDensity.current
|
||||
Button(onClick = { onScaleChange(density.density) }) { Text("Reset") }
|
||||
Switcher(darkMode, text = "Dark Mode", onCheckStateChange = { onDarkModeChange(it) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun AppWindowBorder(
|
||||
modifier: Modifier = Modifier /*= Modifier.border(0.1.dp,FluentTheme.colors.shades.light2,RoundedCornerShape(8.dp))*/,
|
||||
shape: Shape = RoundedCornerShape(8.dp), Content: @Composable () -> Unit
|
||||
) =
|
||||
Layer(
|
||||
modifier,
|
||||
shape = shape
|
||||
) {
|
||||
Content()
|
||||
}
|
||||
|
||||
|
||||
110
desktop/src/jvmMain/kotlin/TitleBar.kt
Normal file
110
desktop/src/jvmMain/kotlin/TitleBar.kt
Normal file
@ -0,0 +1,110 @@
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.gestures.draggable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.window.WindowDraggableArea
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.WindowPlacement
|
||||
import androidx.compose.ui.window.WindowScope
|
||||
import androidx.compose.ui.window.WindowState
|
||||
import com.konyaco.fluent.FluentTheme
|
||||
import com.konyaco.fluent.component.Icon
|
||||
import com.konyaco.fluent.component.SubtleButton
|
||||
import com.konyaco.fluent.component.Text
|
||||
import com.konyaco.fluent.icons.Icons
|
||||
import com.konyaco.fluent.icons.regular.*
|
||||
|
||||
@Composable
|
||||
fun WindowScope.AppWindowTitleBar(state: WindowState, onClose:()->Unit , onPlacementChange: (Boolean) -> Unit){
|
||||
var maximize by remember {mutableStateOf(false)}
|
||||
var onMaximize by remember { mutableStateOf({ state.placement = WindowPlacement.Maximized }) }
|
||||
when (state.placement) {
|
||||
WindowPlacement.Floating -> {
|
||||
onPlacementChange(true)
|
||||
onMaximize = { state.placement = WindowPlacement.Maximized }
|
||||
maximize=false
|
||||
}
|
||||
WindowPlacement.Maximized -> {
|
||||
onPlacementChange(false)
|
||||
onMaximize = { state.placement = WindowPlacement.Floating }
|
||||
maximize=true
|
||||
}
|
||||
WindowPlacement.Fullscreen -> {
|
||||
onPlacementChange(false)
|
||||
onMaximize = { state.placement = WindowPlacement.Floating }
|
||||
maximize=false
|
||||
}
|
||||
}
|
||||
|
||||
if (maximize)
|
||||
TitleBar(
|
||||
maximize = maximize,
|
||||
onClose = onClose,
|
||||
onMaximize = onMaximize,
|
||||
onMinimize = {state.isMinimized = true},
|
||||
onDoubleClick = onMaximize,
|
||||
)
|
||||
else
|
||||
WindowDraggableArea(Modifier) {
|
||||
TitleBar(
|
||||
maximize = maximize,
|
||||
onClose = onClose,
|
||||
onMaximize = onMaximize,
|
||||
onMinimize = {state.isMinimized = true},
|
||||
onDoubleClick = onMaximize,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TitleBar(
|
||||
maximize:Boolean = false,
|
||||
onClose: () -> Unit = {},
|
||||
onMaximize: () -> Unit = {},
|
||||
onMinimize: () -> Unit = {},
|
||||
onDoubleClick: () -> Unit
|
||||
) =
|
||||
Row(
|
||||
Modifier.fillMaxWidth().height(32.dp)
|
||||
.background(FluentTheme.colors.background.layer.default),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Row(
|
||||
Modifier.fillMaxHeight().padding(10.dp, 0.dp), verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Icon(Icons.Default.Play, contentDescription = null)
|
||||
Text(text = WindowProperty.title)
|
||||
}
|
||||
// Row(Modifier.fillMaxHeight().background(FluentTheme.colors.background.layer.default).combinedClickable(
|
||||
// onClick = {},
|
||||
// onDoubleClick = onDoubleClick,
|
||||
// onLongClick = {}), verticalAlignment = Alignment.CenterVertically
|
||||
// ){
|
||||
// Text("Double Click Area")
|
||||
// }
|
||||
Row(Modifier.fillMaxHeight()) {
|
||||
SubtleButton(
|
||||
modifier = Modifier.fillMaxHeight().width(48.dp),
|
||||
onClick = onMinimize, iconOnly = true
|
||||
) {
|
||||
Icon(Icons.Default.Subtract, contentDescription = null)
|
||||
}
|
||||
// SubtleButton(
|
||||
// modifier = Modifier.fillMaxHeight().width(48.dp),
|
||||
// onClick = onMaximize, iconOnly = true
|
||||
// ) {
|
||||
// Icon(if(maximize) Icons.Default.Window else Icons.Default.Maximize , contentDescription = null)
|
||||
// }
|
||||
SubtleButton(modifier = Modifier.fillMaxHeight().width(48.dp), onClick = onClose, iconOnly = true) {
|
||||
Icon(Icons.Default.Dismiss, contentDescription = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
29
desktop/src/jvmMain/kotlin/Tray.kt
Normal file
29
desktop/src/jvmMain/kotlin/Tray.kt
Normal file
@ -0,0 +1,29 @@
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.res.ResourceLoader
|
||||
import androidx.compose.ui.res.loadImageBitmap
|
||||
import androidx.compose.ui.window.ApplicationScope
|
||||
import androidx.compose.ui.window.Tray
|
||||
|
||||
object TrayIcon : Painter() {
|
||||
override val intrinsicSize = Size(256f, 256f)
|
||||
override fun DrawScope.onDraw() {
|
||||
drawImage(
|
||||
WindowProperty.icon
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ApplicationScope.AppTray(onAction: () -> Unit = {}) = Tray(
|
||||
TrayIcon,
|
||||
tooltip = WindowProperty.title,
|
||||
onAction = onAction,
|
||||
menu = {
|
||||
|
||||
Item("Exit", onClick = ::exitApplication)
|
||||
},
|
||||
)
|
||||
10
desktop/src/jvmMain/kotlin/WindowProperty.kt
Normal file
10
desktop/src/jvmMain/kotlin/WindowProperty.kt
Normal file
@ -0,0 +1,10 @@
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.res.ResourceLoader
|
||||
import androidx.compose.ui.res.loadImageBitmap
|
||||
|
||||
object WindowProperty{
|
||||
val title: String = "Eimusic"
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
val icon : ImageBitmap by lazy { loadImageBitmap(ResourceLoader.Default.load("1234.jpg")) }
|
||||
}
|
||||
BIN
desktop/src/jvmMain/resources/1234.jpg
Normal file
BIN
desktop/src/jvmMain/resources/1234.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
desktop/src/jvmMain/resources/606331.png
Normal file
BIN
desktop/src/jvmMain/resources/606331.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
Reference in New Issue
Block a user