mirror of
https://github.com/amir1376/ab-download-manager.git
synced 2025-02-20 11:43:24 +08:00
Merge pull request #255 from amir1376/feature/ui-scale
feature/ui scale
This commit is contained in:
commit
4de61fdb26
@ -852,7 +852,7 @@ class AppComponent(
|
|||||||
val showOpenSourceLibraries = MutableStateFlow(false)
|
val showOpenSourceLibraries = MutableStateFlow(false)
|
||||||
val showTranslators = MutableStateFlow(false)
|
val showTranslators = MutableStateFlow(false)
|
||||||
val theme = appRepository.theme
|
val theme = appRepository.theme
|
||||||
// val uiScale = appRepository.uiScale
|
val uiScale = appRepository.uiScale
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DownloadDialogManager {
|
interface DownloadDialogManager {
|
||||||
|
@ -9,9 +9,11 @@ import androidx.compose.runtime.collectAsState
|
|||||||
import androidx.compose.ui.unit.DpSize
|
import androidx.compose.ui.unit.DpSize
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
import com.abdownloadmanager.resources.Res
|
import com.abdownloadmanager.resources.Res
|
||||||
import com.abdownloadmanager.resources.*
|
import com.abdownloadmanager.resources.*
|
||||||
import ir.amirab.util.compose.resources.myStringResource
|
import ir.amirab.util.compose.resources.myStringResource
|
||||||
|
import ir.amirab.util.desktop.screen.applyUiScale
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ShowAboutDialog(appComponent: AppComponent) {
|
fun ShowAboutDialog(appComponent: AppComponent) {
|
||||||
@ -41,6 +43,7 @@ fun AboutDialog(
|
|||||||
onRequestToggleMaximize = null,
|
onRequestToggleMaximize = null,
|
||||||
state = rememberWindowState(
|
state = rememberWindowState(
|
||||||
size = DpSize(400.dp, 330.dp)
|
size = DpSize(400.dp, 330.dp)
|
||||||
|
.applyUiScale(LocalUiScale.current)
|
||||||
),
|
),
|
||||||
onCloseRequest = onClose
|
onCloseRequest = onClose
|
||||||
) {
|
) {
|
||||||
|
@ -5,7 +5,6 @@ import com.abdownloadmanager.desktop.pages.addDownload.multiple.AddMultiDownload
|
|||||||
import com.abdownloadmanager.desktop.pages.addDownload.multiple.AddMultiItemPage
|
import com.abdownloadmanager.desktop.pages.addDownload.multiple.AddMultiItemPage
|
||||||
import com.abdownloadmanager.desktop.pages.addDownload.single.AddDownloadPage
|
import com.abdownloadmanager.desktop.pages.addDownload.single.AddDownloadPage
|
||||||
import com.abdownloadmanager.desktop.pages.addDownload.single.AddSingleDownloadComponent
|
import com.abdownloadmanager.desktop.pages.addDownload.single.AddSingleDownloadComponent
|
||||||
import com.abdownloadmanager.desktop.pages.singleDownloadPage.SingleDownloadEffects
|
|
||||||
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
||||||
import com.abdownloadmanager.desktop.ui.customwindow.WindowIcon
|
import com.abdownloadmanager.desktop.ui.customwindow.WindowIcon
|
||||||
import com.abdownloadmanager.desktop.ui.customwindow.WindowTitle
|
import com.abdownloadmanager.desktop.ui.customwindow.WindowTitle
|
||||||
@ -19,9 +18,10 @@ import androidx.compose.ui.unit.DpSize
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.WindowPosition
|
import androidx.compose.ui.window.WindowPosition
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
import com.abdownloadmanager.resources.Res
|
import com.abdownloadmanager.resources.Res
|
||||||
import com.abdownloadmanager.resources.*
|
|
||||||
import ir.amirab.util.compose.resources.myStringResource
|
import ir.amirab.util.compose.resources.myStringResource
|
||||||
|
import ir.amirab.util.desktop.screen.applyUiScale
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -32,10 +32,11 @@ fun ShowAddDownloadDialogs(component: AddDownloadDialogManager) {
|
|||||||
val onRequestClose = {
|
val onRequestClose = {
|
||||||
component.closeAddDownloadDialog(addDownloadComponent.id)
|
component.closeAddDownloadDialog(addDownloadComponent.id)
|
||||||
}
|
}
|
||||||
|
val uiScale = LocalUiScale.current
|
||||||
when (addDownloadComponent) {
|
when (addDownloadComponent) {
|
||||||
is AddSingleDownloadComponent -> {
|
is AddSingleDownloadComponent -> {
|
||||||
val h = 265
|
val h = 265.applyUiScale(uiScale)
|
||||||
val w = 500
|
val w = 500.applyUiScale(uiScale)
|
||||||
val size = remember {
|
val size = remember {
|
||||||
DpSize(
|
DpSize(
|
||||||
height = h.dp,
|
height = h.dp,
|
||||||
|
@ -22,6 +22,8 @@ import androidx.compose.ui.unit.DpSize
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.rememberDialogState
|
import androidx.compose.ui.window.rememberDialogState
|
||||||
import com.abdownloadmanager.desktop.pages.settings.configurable.Configurable
|
import com.abdownloadmanager.desktop.pages.settings.configurable.Configurable
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
|
import ir.amirab.util.desktop.screen.applyUiScale
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
import java.awt.MouseInfo
|
import java.awt.MouseInfo
|
||||||
|
|
||||||
@ -36,7 +38,7 @@ fun ExtraConfig(
|
|||||||
size = DpSize(
|
size = DpSize(
|
||||||
height = h.dp,
|
height = h.dp,
|
||||||
width = w.dp,
|
width = w.dp,
|
||||||
),
|
).applyUiScale(LocalUiScale.current),
|
||||||
)
|
)
|
||||||
BaseOptionDialog(onDismiss, state) {
|
BaseOptionDialog(onDismiss, state) {
|
||||||
LaunchedEffect(window){
|
LaunchedEffect(window){
|
||||||
|
@ -7,13 +7,16 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.window.WindowPosition
|
import androidx.compose.ui.window.WindowPosition
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
import com.abdownloadmanager.desktop.utils.mvi.HandleEffects
|
import com.abdownloadmanager.desktop.utils.mvi.HandleEffects
|
||||||
|
import ir.amirab.util.desktop.screen.applyUiScale
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BatchDownloadWindow(batchDownloadComponent: BatchDownloadComponent) {
|
fun BatchDownloadWindow(batchDownloadComponent: BatchDownloadComponent) {
|
||||||
CustomWindow(
|
CustomWindow(
|
||||||
state = rememberWindowState(
|
state = rememberWindowState(
|
||||||
size = DpSize(500.dp, 420.dp),
|
size = DpSize(500.dp, 420.dp)
|
||||||
|
.applyUiScale(LocalUiScale.current),
|
||||||
position = WindowPosition(Alignment.Center)
|
position = WindowPosition(Alignment.Center)
|
||||||
),
|
),
|
||||||
onCloseRequest = batchDownloadComponent.onClose
|
onCloseRequest = batchDownloadComponent.onClose
|
||||||
|
@ -9,6 +9,8 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.window.WindowPosition
|
import androidx.compose.ui.window.WindowPosition
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
|
import ir.amirab.util.desktop.screen.applyUiScale
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ShowCategoryDialogs(dialogManager: CategoryDialogManager) {
|
fun ShowCategoryDialogs(dialogManager: CategoryDialogManager) {
|
||||||
@ -28,7 +30,7 @@ private fun CategoryDialog(
|
|||||||
},
|
},
|
||||||
alwaysOnTop = true,
|
alwaysOnTop = true,
|
||||||
state = rememberWindowState(
|
state = rememberWindowState(
|
||||||
size = DpSize(350.dp, 400.dp),
|
size = DpSize(350.dp, 400.dp).applyUiScale(LocalUiScale.current),
|
||||||
position = WindowPosition.Aligned(Alignment.Center),
|
position = WindowPosition.Aligned(Alignment.Center),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
@ -33,6 +33,7 @@ import androidx.compose.ui.window.*
|
|||||||
import com.abdownloadmanager.desktop.pages.addDownload.shared.ExtraConfig
|
import com.abdownloadmanager.desktop.pages.addDownload.shared.ExtraConfig
|
||||||
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
||||||
import com.abdownloadmanager.desktop.ui.customwindow.WindowTitle
|
import com.abdownloadmanager.desktop.ui.customwindow.WindowTitle
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
import com.abdownloadmanager.desktop.ui.util.ifThen
|
import com.abdownloadmanager.desktop.ui.util.ifThen
|
||||||
import com.abdownloadmanager.desktop.utils.mvi.HandleEffects
|
import com.abdownloadmanager.desktop.utils.mvi.HandleEffects
|
||||||
import com.abdownloadmanager.resources.Res
|
import com.abdownloadmanager.resources.Res
|
||||||
@ -41,6 +42,7 @@ import com.abdownloadmanager.utils.compose.WithContentColor
|
|||||||
import ir.amirab.util.UrlUtils
|
import ir.amirab.util.UrlUtils
|
||||||
import ir.amirab.util.compose.resources.myStringResource
|
import ir.amirab.util.compose.resources.myStringResource
|
||||||
import ir.amirab.util.compose.asStringSource
|
import ir.amirab.util.compose.asStringSource
|
||||||
|
import ir.amirab.util.desktop.screen.applyUiScale
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EditDownloadWindow(
|
fun EditDownloadWindow(
|
||||||
@ -48,7 +50,8 @@ fun EditDownloadWindow(
|
|||||||
) {
|
) {
|
||||||
CustomWindow(
|
CustomWindow(
|
||||||
state = rememberWindowState(
|
state = rememberWindowState(
|
||||||
size = DpSize(450.dp, 230.dp),
|
size = DpSize(450.dp, 230.dp)
|
||||||
|
.applyUiScale(LocalUiScale.current),
|
||||||
position = WindowPosition.Aligned(Alignment.Center)
|
position = WindowPosition.Aligned(Alignment.Center)
|
||||||
),
|
),
|
||||||
alwaysOnTop = true,
|
alwaysOnTop = true,
|
||||||
|
@ -9,6 +9,8 @@ import androidx.compose.ui.unit.DpSize
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.WindowPosition
|
import androidx.compose.ui.window.WindowPosition
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
|
import ir.amirab.util.desktop.screen.applyUiScale
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NewQueueDialog(
|
fun NewQueueDialog(
|
||||||
@ -17,7 +19,8 @@ fun NewQueueDialog(
|
|||||||
if (appComponent.showCreateQueueDialog.collectAsState().value){
|
if (appComponent.showCreateQueueDialog.collectAsState().value){
|
||||||
CustomWindow(
|
CustomWindow(
|
||||||
state = rememberWindowState(
|
state = rememberWindowState(
|
||||||
size = DpSize(width = 300.dp, height = 130.dp),
|
size = DpSize(width = 300.dp, height = 130.dp)
|
||||||
|
.applyUiScale(LocalUiScale.current),
|
||||||
position = WindowPosition.Aligned(Alignment.Center),
|
position = WindowPosition.Aligned(Alignment.Center),
|
||||||
),
|
),
|
||||||
resizable = false,
|
resizable = false,
|
||||||
|
@ -1,16 +1,9 @@
|
|||||||
package com.abdownloadmanager.desktop.pages.settings
|
package com.abdownloadmanager.desktop.pages.settings
|
||||||
|
|
||||||
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
|
||||||
import com.abdownloadmanager.desktop.ui.theme.myColors
|
|
||||||
import com.abdownloadmanager.desktop.utils.mvi.HandleEffects
|
import com.abdownloadmanager.desktop.utils.mvi.HandleEffects
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.DpSize
|
import androidx.compose.ui.unit.DpSize
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.WindowPosition
|
import androidx.compose.ui.window.WindowPosition
|
||||||
|
@ -199,17 +199,17 @@ fun proxyConfig(proxyManager: ProxyManager, scope: CoroutineScope): ProxyConfigu
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
fun uiScaleConfig(appSettings: AppSettingsStorage): EnumConfigurable<Float?> {
|
||||||
fun uiScaleConfig(appSettings: AppSettings): EnumConfigurable<Float?> {
|
|
||||||
return EnumConfigurable(
|
return EnumConfigurable(
|
||||||
title = "Ui Scale",
|
title = Res.string.settings_ui_scale.asStringSource(),
|
||||||
description = "Scale Ui Elements",
|
description = Res.string.settings_ui_scale_description.asStringSource(),
|
||||||
backedBy = appSettings.uiScale,
|
backedBy = appSettings.uiScale,
|
||||||
possibleValues = listOf(
|
possibleValues = listOf(
|
||||||
null,
|
null,
|
||||||
0.5f,
|
0.8f,
|
||||||
0.75f,
|
0.9f,
|
||||||
1f,
|
1f,
|
||||||
|
1.1f,
|
||||||
1.25f,
|
1.25f,
|
||||||
1.5f,
|
1.5f,
|
||||||
1.75f,
|
1.75f,
|
||||||
@ -218,14 +218,13 @@ fun uiScaleConfig(appSettings: AppSettings): EnumConfigurable<Float?> {
|
|||||||
renderMode = EnumConfigurable.RenderMode.Spinner,
|
renderMode = EnumConfigurable.RenderMode.Spinner,
|
||||||
describe = {
|
describe = {
|
||||||
if (it == null) {
|
if (it == null) {
|
||||||
"System"
|
Res.string.system.asStringSource()
|
||||||
} else {
|
} else {
|
||||||
"$it x"
|
"$it x".asStringSource()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
fun themeConfig(
|
fun themeConfig(
|
||||||
themeManager: ThemeManager,
|
themeManager: ThemeManager,
|
||||||
@ -377,7 +376,7 @@ class SettingsComponent(
|
|||||||
Appearance -> listOf(
|
Appearance -> listOf(
|
||||||
themeConfig(themeManager, scope),
|
themeConfig(themeManager, scope),
|
||||||
languageConfig(languageManager, scope),
|
languageConfig(languageManager, scope),
|
||||||
// uiScaleConfig(appSettings),
|
uiScaleConfig(appSettings),
|
||||||
autoStartConfig(appSettings),
|
autoStartConfig(appSettings),
|
||||||
mergeTopBarWithTitleBarConfig(appSettings),
|
mergeTopBarWithTitleBarConfig(appSettings),
|
||||||
playSoundNotification(appSettings),
|
playSoundNotification(appSettings),
|
||||||
|
@ -14,12 +14,14 @@ import androidx.compose.ui.window.FrameWindowScope
|
|||||||
import androidx.compose.ui.window.WindowPosition
|
import androidx.compose.ui.window.WindowPosition
|
||||||
import androidx.compose.ui.window.WindowState
|
import androidx.compose.ui.window.WindowState
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
import ir.amirab.downloader.downloaditem.DownloadJobStatus
|
import ir.amirab.downloader.downloaditem.DownloadJobStatus
|
||||||
import ir.amirab.downloader.monitor.CompletedDownloadItemState
|
import ir.amirab.downloader.monitor.CompletedDownloadItemState
|
||||||
import ir.amirab.downloader.monitor.IDownloadItemState
|
import ir.amirab.downloader.monitor.IDownloadItemState
|
||||||
import ir.amirab.downloader.monitor.ProcessingDownloadItemState
|
import ir.amirab.downloader.monitor.ProcessingDownloadItemState
|
||||||
import ir.amirab.downloader.monitor.statusOrFinished
|
import ir.amirab.downloader.monitor.statusOrFinished
|
||||||
import ir.amirab.downloader.utils.ExceptionUtils
|
import ir.amirab.downloader.utils.ExceptionUtils
|
||||||
|
import ir.amirab.util.desktop.screen.applyUiScale
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
import java.awt.Taskbar
|
import java.awt.Taskbar
|
||||||
import java.awt.Window
|
import java.awt.Window
|
||||||
@ -110,9 +112,12 @@ private fun CompletedWindow(
|
|||||||
}
|
}
|
||||||
val defaultHeight = 160f
|
val defaultHeight = 160f
|
||||||
val defaultWidth = 450f
|
val defaultWidth = 450f
|
||||||
|
val uiScale = LocalUiScale.current
|
||||||
val state = rememberWindowState(
|
val state = rememberWindowState(
|
||||||
height = defaultHeight.dp,
|
size = DpSize(
|
||||||
width = defaultWidth.dp,
|
height = defaultHeight.dp,
|
||||||
|
width = defaultWidth.dp
|
||||||
|
).applyUiScale(uiScale),
|
||||||
position = WindowPosition(Alignment.Center)
|
position = WindowPosition(Alignment.Center)
|
||||||
)
|
)
|
||||||
CustomWindow(
|
CustomWindow(
|
||||||
@ -136,7 +141,7 @@ private fun CompletedWindow(
|
|||||||
state.size = DpSize(
|
state.size = DpSize(
|
||||||
width = w.dp,
|
width = w.dp,
|
||||||
height = h.dp
|
height = h.dp
|
||||||
)
|
).applyUiScale(uiScale)
|
||||||
}
|
}
|
||||||
CompletedDownloadPage(
|
CompletedDownloadPage(
|
||||||
singleDownloadComponent,
|
singleDownloadComponent,
|
||||||
@ -153,8 +158,9 @@ private fun ProgressWindow(
|
|||||||
val onRequestClose = {
|
val onRequestClose = {
|
||||||
singleDownloadComponent.close()
|
singleDownloadComponent.close()
|
||||||
}
|
}
|
||||||
val defaultHeight = 290f
|
val uiScale = LocalUiScale.current
|
||||||
val defaultWidth = 450f
|
val defaultHeight = 290f.applyUiScale(uiScale)
|
||||||
|
val defaultWidth = 450f.applyUiScale(uiScale)
|
||||||
|
|
||||||
val showPartInfo by singleDownloadComponent.showPartInfo.collectAsState()
|
val showPartInfo by singleDownloadComponent.showPartInfo.collectAsState()
|
||||||
val state = rememberWindowState(
|
val state = rememberWindowState(
|
||||||
@ -181,6 +187,7 @@ private fun ProgressWindow(
|
|||||||
var w = defaultWidth
|
var w = defaultWidth
|
||||||
if (showPartInfo) {
|
if (showPartInfo) {
|
||||||
h += singleDownloadPageSizing.partInfoHeight.value
|
h += singleDownloadPageSizing.partInfoHeight.value
|
||||||
|
.applyUiScale(uiScale)
|
||||||
}
|
}
|
||||||
LaunchedEffect(w, h) {
|
LaunchedEffect(w, h) {
|
||||||
state.size = DpSize(
|
state.size = DpSize(
|
||||||
|
@ -23,7 +23,7 @@ class AppRepository : KoinComponent {
|
|||||||
private val proxyManager: ProxyManager by inject()
|
private val proxyManager: ProxyManager by inject()
|
||||||
val theme = appSettings.theme
|
val theme = appSettings.theme
|
||||||
|
|
||||||
// val uiScale = appSettings.uiScale
|
val uiScale = appSettings.uiScale
|
||||||
private val downloadSystem : DownloadSystem by inject()
|
private val downloadSystem : DownloadSystem by inject()
|
||||||
private val downloadSettings: DownloadSettings by inject()
|
private val downloadSettings: DownloadSettings by inject()
|
||||||
private val downloadManager: DownloadManager = downloadSystem.downloadManager
|
private val downloadManager: DownloadManager = downloadSystem.downloadManager
|
||||||
|
@ -4,6 +4,7 @@ import com.abdownloadmanager.desktop.utils.*
|
|||||||
import androidx.datastore.core.DataStore
|
import androidx.datastore.core.DataStore
|
||||||
import arrow.optics.Lens
|
import arrow.optics.Lens
|
||||||
import arrow.optics.optics
|
import arrow.optics.optics
|
||||||
|
import com.abdownloadmanager.desktop.App
|
||||||
import ir.amirab.util.compose.localizationmanager.LanguageStorage
|
import ir.amirab.util.compose.localizationmanager.LanguageStorage
|
||||||
import ir.amirab.util.config.*
|
import ir.amirab.util.config.*
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@ -15,6 +16,7 @@ import java.io.File
|
|||||||
data class AppSettingsModel(
|
data class AppSettingsModel(
|
||||||
val theme: String = "dark",
|
val theme: String = "dark",
|
||||||
val language: String = "en",
|
val language: String = "en",
|
||||||
|
val uiScale: Float? = null,
|
||||||
val mergeTopBarWithTitleBar: Boolean = false,
|
val mergeTopBarWithTitleBar: Boolean = false,
|
||||||
val threadCount: Int = 8,
|
val threadCount: Int = 8,
|
||||||
val dynamicPartCreation: Boolean = true,
|
val dynamicPartCreation: Boolean = true,
|
||||||
@ -40,6 +42,7 @@ data class AppSettingsModel(
|
|||||||
object Keys {
|
object Keys {
|
||||||
val theme = stringKeyOf("theme")
|
val theme = stringKeyOf("theme")
|
||||||
val language = stringKeyOf("language")
|
val language = stringKeyOf("language")
|
||||||
|
val uiScale = floatKeyOf("uiScale")
|
||||||
val mergeTopBarWithTitleBar = booleanKeyOf("mergeTopBarWithTitleBar")
|
val mergeTopBarWithTitleBar = booleanKeyOf("mergeTopBarWithTitleBar")
|
||||||
val threadCount = intKeyOf("threadCount")
|
val threadCount = intKeyOf("threadCount")
|
||||||
val dynamicPartCreation = booleanKeyOf("dynamicPartCreation")
|
val dynamicPartCreation = booleanKeyOf("dynamicPartCreation")
|
||||||
@ -57,12 +60,12 @@ data class AppSettingsModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun get(source: MapConfig): AppSettingsModel {
|
override fun get(source: MapConfig): AppSettingsModel {
|
||||||
val default by lazy { AppSettingsModel.default }
|
val default by lazy { AppSettingsModel.default }
|
||||||
return AppSettingsModel(
|
return AppSettingsModel(
|
||||||
theme = source.get(Keys.theme) ?: default.theme,
|
theme = source.get(Keys.theme) ?: default.theme,
|
||||||
language = source.get(Keys.language) ?: default.language,
|
language = source.get(Keys.language) ?: default.language,
|
||||||
|
uiScale = source.get(Keys.uiScale) ?: default.uiScale,
|
||||||
mergeTopBarWithTitleBar = source.get(Keys.mergeTopBarWithTitleBar) ?: default.mergeTopBarWithTitleBar,
|
mergeTopBarWithTitleBar = source.get(Keys.mergeTopBarWithTitleBar) ?: default.mergeTopBarWithTitleBar,
|
||||||
threadCount = source.get(Keys.threadCount) ?: default.threadCount,
|
threadCount = source.get(Keys.threadCount) ?: default.threadCount,
|
||||||
dynamicPartCreation = source.get(Keys.dynamicPartCreation) ?: default.dynamicPartCreation,
|
dynamicPartCreation = source.get(Keys.dynamicPartCreation) ?: default.dynamicPartCreation,
|
||||||
@ -88,6 +91,7 @@ data class AppSettingsModel(
|
|||||||
return source.apply {
|
return source.apply {
|
||||||
put(Keys.theme, focus.theme)
|
put(Keys.theme, focus.theme)
|
||||||
put(Keys.language, focus.language)
|
put(Keys.language, focus.language)
|
||||||
|
putNullable(Keys.uiScale, focus.uiScale)
|
||||||
put(Keys.mergeTopBarWithTitleBar, focus.mergeTopBarWithTitleBar)
|
put(Keys.mergeTopBarWithTitleBar, focus.mergeTopBarWithTitleBar)
|
||||||
put(Keys.threadCount, focus.threadCount)
|
put(Keys.threadCount, focus.threadCount)
|
||||||
put(Keys.dynamicPartCreation, focus.dynamicPartCreation)
|
put(Keys.dynamicPartCreation, focus.dynamicPartCreation)
|
||||||
@ -107,6 +111,16 @@ data class AppSettingsModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val uiScaleLens: Lens<AppSettingsModel, Float?>
|
||||||
|
get() = Lens(
|
||||||
|
get = {
|
||||||
|
it.uiScale
|
||||||
|
},
|
||||||
|
set = { s, f ->
|
||||||
|
s.copy(uiScale = f)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
class AppSettingsStorage(
|
class AppSettingsStorage(
|
||||||
settings: DataStore<MapConfig>,
|
settings: DataStore<MapConfig>,
|
||||||
) :
|
) :
|
||||||
@ -114,6 +128,7 @@ class AppSettingsStorage(
|
|||||||
LanguageStorage {
|
LanguageStorage {
|
||||||
var theme = from(AppSettingsModel.theme)
|
var theme = from(AppSettingsModel.theme)
|
||||||
override val selectedLanguage = from(AppSettingsModel.language)
|
override val selectedLanguage = from(AppSettingsModel.language)
|
||||||
|
var uiScale = from(uiScaleLens)
|
||||||
var mergeTopBarWithTitleBar = from(AppSettingsModel.mergeTopBarWithTitleBar)
|
var mergeTopBarWithTitleBar = from(AppSettingsModel.mergeTopBarWithTitleBar)
|
||||||
val threadCount = from(AppSettingsModel.threadCount)
|
val threadCount = from(AppSettingsModel.threadCount)
|
||||||
val dynamicPartCreation = from(AppSettingsModel.dynamicPartCreation)
|
val dynamicPartCreation = from(AppSettingsModel.dynamicPartCreation)
|
||||||
|
@ -60,7 +60,7 @@ object Ui : KoinComponent {
|
|||||||
ProvideNotificationManager {
|
ProvideNotificationManager {
|
||||||
ABDownloaderTheme(
|
ABDownloaderTheme(
|
||||||
myColors = theme,
|
myColors = theme,
|
||||||
// uiScale = appComponent.uiScale.collectAsState().value
|
uiScale = appComponent.uiScale.collectAsState().value
|
||||||
) {
|
) {
|
||||||
ProvideGlobalExceptionHandler(globalAppExceptionHandler) {
|
ProvideGlobalExceptionHandler(globalAppExceptionHandler) {
|
||||||
val trayState = rememberTrayState()
|
val trayState = rememberTrayState()
|
||||||
|
@ -5,7 +5,7 @@ import com.abdownloadmanager.utils.compose.WithContentAlpha
|
|||||||
import com.abdownloadmanager.utils.compose.WithContentColor
|
import com.abdownloadmanager.utils.compose.WithContentColor
|
||||||
import ir.amirab.util.compose.IconSource
|
import ir.amirab.util.compose.IconSource
|
||||||
import com.abdownloadmanager.desktop.ui.icon.MyIcons
|
import com.abdownloadmanager.desktop.ui.icon.MyIcons
|
||||||
//import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
import com.abdownloadmanager.desktop.ui.theme.myColors
|
import com.abdownloadmanager.desktop.ui.theme.myColors
|
||||||
import com.abdownloadmanager.desktop.ui.theme.myTextSizes
|
import com.abdownloadmanager.desktop.ui.theme.myTextSizes
|
||||||
import com.abdownloadmanager.desktop.utils.*
|
import com.abdownloadmanager.desktop.utils.*
|
||||||
@ -25,9 +25,11 @@ import androidx.compose.ui.graphics.RectangleShape
|
|||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.graphics.takeOrElse
|
import androidx.compose.ui.graphics.takeOrElse
|
||||||
import androidx.compose.ui.input.key.KeyEvent
|
import androidx.compose.ui.input.key.KeyEvent
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||||
import androidx.compose.ui.platform.LocalWindowInfo
|
import androidx.compose.ui.platform.LocalWindowInfo
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.Density
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.FrameWindowScope
|
import androidx.compose.ui.window.FrameWindowScope
|
||||||
import androidx.compose.ui.window.Window
|
import androidx.compose.ui.window.Window
|
||||||
@ -323,52 +325,63 @@ fun CustomWindow(
|
|||||||
else Color.Black
|
else Color.Black
|
||||||
}.toWindowColorType()
|
}.toWindowColorType()
|
||||||
}
|
}
|
||||||
CompositionLocalProvider(
|
UiScaledContent {
|
||||||
LocalWindowController provides windowController,
|
CompositionLocalProvider(
|
||||||
LocalWindowState provides state,
|
LocalWindowController provides windowController,
|
||||||
LocalWindow provides window,
|
LocalWindowState provides state,
|
||||||
) {
|
LocalWindow provides window,
|
||||||
if (preventMinimize) {
|
|
||||||
PreventMinimize()
|
|
||||||
}
|
|
||||||
// a window frame which totally rendered with compose
|
|
||||||
CustomWindowFrame(
|
|
||||||
onRequestMinimize = onRequestMinimize,
|
|
||||||
onRequestClose = onCloseRequest,
|
|
||||||
onRequestToggleMaximize = onRequestToggleMaximize,
|
|
||||||
title = title,
|
|
||||||
titlePosition = titlePosition,
|
|
||||||
windowIcon = icon,
|
|
||||||
background = background,
|
|
||||||
onBackground = myColors.onBackground,
|
|
||||||
start = start,
|
|
||||||
end = end,
|
|
||||||
) {
|
) {
|
||||||
// val defaultDensity = LocalDensity.current
|
if (preventMinimize) {
|
||||||
// val uiScale = LocalUiScale.current
|
PreventMinimize()
|
||||||
// val density = remember(uiScale) {
|
}
|
||||||
// if (uiScale == null) {
|
// a window frame which totally rendered with compose
|
||||||
// defaultDensity
|
CustomWindowFrame(
|
||||||
// } else {
|
onRequestMinimize = onRequestMinimize,
|
||||||
// Density(uiScale)
|
onRequestClose = onCloseRequest,
|
||||||
// }
|
onRequestToggleMaximize = onRequestToggleMaximize,
|
||||||
// }
|
title = title,
|
||||||
// CompositionLocalProvider(
|
titlePosition = titlePosition,
|
||||||
// LocalDensity provides density
|
windowIcon = icon,
|
||||||
// ) {
|
background = background,
|
||||||
ResponsiveBox {
|
onBackground = myColors.onBackground,
|
||||||
Box(Modifier.clearFocusOnTap()) {
|
start = start,
|
||||||
PopUpContainer {
|
end = end,
|
||||||
content()
|
) {
|
||||||
|
ResponsiveBox {
|
||||||
|
Box(Modifier.clearFocusOnTap()) {
|
||||||
|
PopUpContainer {
|
||||||
|
content()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* put this in every window because [Window] composable override [LocalDensity]
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun UiScaledContent(
|
||||||
|
defaultDensity: Density = LocalDensity.current,
|
||||||
|
uiScale: Float? = LocalUiScale.current,
|
||||||
|
content: @Composable () -> Unit,
|
||||||
|
) {
|
||||||
|
val density = remember(uiScale) {
|
||||||
|
if (uiScale == null) {
|
||||||
|
defaultDensity
|
||||||
|
} else {
|
||||||
|
Density(uiScale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CompositionLocalProvider(
|
||||||
|
LocalDensity provides density,
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun PreventMinimize() {
|
private fun PreventMinimize() {
|
||||||
val state = LocalWindowState.current
|
val state = LocalWindowState.current
|
||||||
|
@ -10,7 +10,7 @@ import java.awt.event.WindowFocusListener
|
|||||||
fun BaseOptionDialog(
|
fun BaseOptionDialog(
|
||||||
onCloseRequest: () -> Unit,
|
onCloseRequest: () -> Unit,
|
||||||
state: DialogState = rememberDialogState(),
|
state: DialogState = rememberDialogState(),
|
||||||
resizeable:Boolean=true,
|
resizeable: Boolean = true,
|
||||||
content: @Composable WindowScope.() -> Unit,
|
content: @Composable WindowScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
DialogWindow(
|
DialogWindow(
|
||||||
@ -21,7 +21,7 @@ fun BaseOptionDialog(
|
|||||||
resizable = resizeable,
|
resizable = resizeable,
|
||||||
onCloseRequest = onCloseRequest,
|
onCloseRequest = onCloseRequest,
|
||||||
) {
|
) {
|
||||||
val focusListener=remember {
|
val focusListener = remember {
|
||||||
object : WindowFocusListener {
|
object : WindowFocusListener {
|
||||||
override fun windowGainedFocus(e: WindowEvent?) {
|
override fun windowGainedFocus(e: WindowEvent?) {
|
||||||
//do nothing
|
//do nothing
|
||||||
@ -32,16 +32,18 @@ fun BaseOptionDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DisposableEffect(window){
|
DisposableEffect(window) {
|
||||||
window.addWindowFocusListener(focusListener);
|
window.addWindowFocusListener(focusListener);
|
||||||
window.isAlwaysOnTop=true
|
window.isAlwaysOnTop = true
|
||||||
//we need this to allow click outside
|
//we need this to allow click outside
|
||||||
window.modalityType=java.awt.Dialog.ModalityType.MODELESS
|
window.modalityType = java.awt.Dialog.ModalityType.MODELESS
|
||||||
onDispose{
|
onDispose {
|
||||||
window.removeWindowFocusListener(focusListener)
|
window.removeWindowFocusListener(focusListener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// window.subtractInset()
|
// window.subtractInset()
|
||||||
content()
|
UiScaledContent {
|
||||||
|
content()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,12 +12,15 @@ import androidx.compose.foundation.*
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.unit.Density
|
||||||
import androidx.compose.ui.unit.TextUnit
|
import androidx.compose.ui.unit.TextUnit
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.compose.ui.window.Popup
|
import androidx.compose.ui.window.Popup
|
||||||
import androidx.compose.ui.window.PopupProperties
|
import androidx.compose.ui.window.PopupProperties
|
||||||
import androidx.compose.ui.window.rememberPopupPositionProviderAtPosition
|
import androidx.compose.ui.window.rememberPopupPositionProviderAtPosition
|
||||||
|
import com.abdownloadmanager.desktop.ui.customwindow.UiScaledContent
|
||||||
import ir.amirab.util.compose.asStringSource
|
import ir.amirab.util.compose.asStringSource
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -101,12 +104,14 @@ private val textSizes = TextSizes(
|
|||||||
@Composable
|
@Composable
|
||||||
fun ABDownloaderTheme(
|
fun ABDownloaderTheme(
|
||||||
myColors: MyColors,
|
myColors: MyColors,
|
||||||
// uiScale: Float? = null,
|
uiScale: Float? = null,
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
val systemDensity = LocalDensity.current
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalMyColors provides AnimatedColors(myColors, tween(500)),
|
LocalMyColors provides AnimatedColors(myColors, tween(500)),
|
||||||
// LocalUiScale provides uiScale,
|
LocalUiScale provides uiScale,
|
||||||
|
LocalSystemDensity provides systemDensity,
|
||||||
) {
|
) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalContextMenuRepresentation provides myContextMenuRepresentation(),
|
LocalContextMenuRepresentation provides myContextMenuRepresentation(),
|
||||||
@ -120,7 +125,11 @@ fun ABDownloaderTheme(
|
|||||||
fontSize = textSizes.base,
|
fontSize = textSizes.base,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
content()
|
// it is overridden by [Window] Composable,
|
||||||
|
// but I put this here. maybe I need this outside of window scope!
|
||||||
|
UiScaledContent {
|
||||||
|
content()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,7 +181,7 @@ private fun myDefaultScrollBarStyle(): ScrollbarStyle {
|
|||||||
thickness = 12.dp,
|
thickness = 12.dp,
|
||||||
shape = RoundedCornerShape(4.dp),
|
shape = RoundedCornerShape(4.dp),
|
||||||
hoverDurationMillis = 300,
|
hoverDurationMillis = 300,
|
||||||
unhoverColor = myColors.onBackground/10,
|
unhoverColor = myColors.onBackground / 10,
|
||||||
hoverColor = myColors.onBackground/30
|
hoverColor = myColors.onBackground / 30
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,11 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.runtime.compositionLocalOf
|
import androidx.compose.runtime.compositionLocalOf
|
||||||
import androidx.compose.runtime.staticCompositionLocalOf
|
import androidx.compose.runtime.staticCompositionLocalOf
|
||||||
|
import androidx.compose.ui.unit.Density
|
||||||
import androidx.compose.ui.unit.TextUnit
|
import androidx.compose.ui.unit.TextUnit
|
||||||
|
|
||||||
//val LocalUiScale = staticCompositionLocalOf { null as Float? }
|
val LocalSystemDensity = staticCompositionLocalOf<Density?> { null }
|
||||||
|
val LocalUiScale = staticCompositionLocalOf<Float?> { null }
|
||||||
|
|
||||||
val LocalTextSizes = compositionLocalOf<TextSizes> {
|
val LocalTextSizes = compositionLocalOf<TextSizes> {
|
||||||
error("LocalTextSizes not provided")
|
error("LocalTextSizes not provided")
|
||||||
|
@ -18,9 +18,11 @@ import androidx.compose.ui.unit.DpSize
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.WindowPosition
|
import androidx.compose.ui.window.WindowPosition
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
import com.abdownloadmanager.resources.Res
|
import com.abdownloadmanager.resources.Res
|
||||||
import ir.amirab.util.compose.StringSource
|
import ir.amirab.util.compose.StringSource
|
||||||
import ir.amirab.util.compose.resources.myStringResource
|
import ir.amirab.util.compose.resources.myStringResource
|
||||||
|
import ir.amirab.util.desktop.screen.applyUiScale
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@ -39,8 +41,9 @@ fun ConfirmDialog(
|
|||||||
onConfirm: () -> Unit,
|
onConfirm: () -> Unit,
|
||||||
onCancel: () -> Unit,
|
onCancel: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val h = 180
|
val uiScale = LocalUiScale.current
|
||||||
val w = 400
|
val h = 180.applyUiScale(uiScale)
|
||||||
|
val w = 400.applyUiScale(uiScale)
|
||||||
val state = rememberWindowState(
|
val state = rememberWindowState(
|
||||||
size = DpSize(w.dp, h.dp),
|
size = DpSize(w.dp, h.dp),
|
||||||
position = WindowPosition.Aligned(Alignment.Center)
|
position = WindowPosition.Aligned(Alignment.Center)
|
||||||
|
@ -19,7 +19,9 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.unit.DpSize
|
import androidx.compose.ui.unit.DpSize
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
|
||||||
import ir.amirab.util.compose.StringSource
|
import ir.amirab.util.compose.StringSource
|
||||||
|
import ir.amirab.util.desktop.screen.applyUiScale
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@ -59,8 +61,9 @@ fun MessageDialog(
|
|||||||
msgContent: MessageDialogModel,
|
msgContent: MessageDialogModel,
|
||||||
onConfirm: () -> Unit,
|
onConfirm: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val h = 200
|
val uiScale = LocalUiScale.current
|
||||||
val w = 400
|
val h = 200.applyUiScale(uiScale)
|
||||||
|
val w = 400.applyUiScale(uiScale)
|
||||||
val state = rememberWindowState(
|
val state = rememberWindowState(
|
||||||
size = DpSize(w.dp, h.dp)
|
size = DpSize(w.dp, h.dp)
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
plugins{
|
plugins{
|
||||||
id(MyPlugins.kotlin)
|
id(MyPlugins.kotlin)
|
||||||
id(MyPlugins.composeDesktop)
|
id(MyPlugins.composeDesktop)
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":desktop:shared"))
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
package ir.amirab.util.customwindow
|
package ir.amirab.util.customwindow
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@ -6,16 +7,17 @@ import androidx.compose.ui.composed
|
|||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
import androidx.compose.ui.layout.positionInWindow
|
import androidx.compose.ui.layout.positionInWindow
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
|
||||||
import androidx.compose.ui.platform.LocalWindowInfo
|
import androidx.compose.ui.platform.LocalWindowInfo
|
||||||
import androidx.compose.ui.unit.*
|
import androidx.compose.ui.unit.*
|
||||||
import androidx.compose.ui.window.FrameWindowScope
|
import androidx.compose.ui.window.FrameWindowScope
|
||||||
import ir.amirab.util.customwindow.util.CustomWindowDecorationAccessing
|
import ir.amirab.util.customwindow.util.CustomWindowDecorationAccessing
|
||||||
|
import ir.amirab.util.desktop.GlobalDensity
|
||||||
import java.awt.Rectangle
|
import java.awt.Rectangle
|
||||||
import java.awt.Shape
|
import java.awt.Shape
|
||||||
import java.awt.Window
|
import java.awt.Window
|
||||||
import java.awt.event.ComponentAdapter
|
import java.awt.event.ComponentAdapter
|
||||||
import java.awt.event.ComponentEvent
|
import java.awt.event.ComponentEvent
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
object HitSpots {
|
object HitSpots {
|
||||||
const val NO_HIT_SPOT = 0
|
const val NO_HIT_SPOT = 0
|
||||||
@ -56,7 +58,9 @@ context (FrameWindowScope)
|
|||||||
private fun Modifier.onPositionInRect(
|
private fun Modifier.onPositionInRect(
|
||||||
onChange: (Rectangle) -> Unit,
|
onChange: (Rectangle) -> Unit,
|
||||||
) = composed {
|
) = composed {
|
||||||
val density = LocalDensity.current
|
// we use Global for sake of awt here.
|
||||||
|
// because we want to calculate height and pass it to awt
|
||||||
|
val density = GlobalDensity
|
||||||
onGloballyPositioned {
|
onGloballyPositioned {
|
||||||
onChange(
|
onChange(
|
||||||
it.positionInWindow().toDpRectangle(
|
it.positionInWindow().toDpRectangle(
|
||||||
@ -114,8 +118,10 @@ context (FrameWindowScope)
|
|||||||
fun ProvideWindowSpotContainer(
|
fun ProvideWindowSpotContainer(
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
// we use Global for sake of awt here.
|
||||||
val windowSize =getCurrentWindowSize()
|
// because we want to calculate height and pass it to awt
|
||||||
|
val density = GlobalDensity
|
||||||
|
val windowSize = getCurrentWindowSize()
|
||||||
val containerSize = with(density) {
|
val containerSize = with(density) {
|
||||||
LocalWindowInfo.current.containerSize.let {
|
LocalWindowInfo.current.containerSize.let {
|
||||||
DpSize(it.width.toDp(), it.height.toDp())
|
DpSize(it.width.toDp(), it.height.toDp())
|
||||||
@ -142,10 +148,15 @@ fun ProvideWindowSpotContainer(
|
|||||||
//
|
//
|
||||||
if (CustomWindowDecorationAccessing.isSupported) {
|
if (CustomWindowDecorationAccessing.isSupported) {
|
||||||
val startOffset = (windowSize - containerSize) / 2
|
val startOffset = (windowSize - containerSize) / 2
|
||||||
val startWidthOffsetInDp = startOffset.width.value.toInt()
|
val startWidthOffsetInDp = startOffset.width.value.roundToInt()
|
||||||
// val startHeightInDp=delta.height.value.toInt() //it seems no need here
|
// val startHeightOffsetInDp = startOffset.width.value.roundToInt() //it seems no need here
|
||||||
val spots: Map<Shape, Int> = spotsWithInfo.values.associate { (rect, spot) ->
|
val spots: Map<Shape, Int> = spotsWithInfo.values.associate { (rect, spot) ->
|
||||||
Rectangle(rect.x + startWidthOffsetInDp, rect.y, rect.width, rect.height) to spot
|
Rectangle(
|
||||||
|
rect.x + startWidthOffsetInDp,
|
||||||
|
rect.y /*+ startHeightOffsetInDp*/,
|
||||||
|
rect.width,
|
||||||
|
rect.height
|
||||||
|
) to spot
|
||||||
}
|
}
|
||||||
placeHitSpots(window, spots, toolbarHeight)
|
placeHitSpots(window, spots, toolbarHeight)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
package ir.amirab.util.desktop.screen
|
||||||
|
|
||||||
|
import androidx.compose.ui.unit.*
|
||||||
|
//import androidx.compose.ui.window.WindowPlacement
|
||||||
|
//import androidx.compose.ui.window.WindowPosition
|
||||||
|
//import androidx.compose.ui.window.WindowState
|
||||||
|
import ir.amirab.util.desktop.GlobalDensity
|
||||||
|
import java.awt.GraphicsEnvironment
|
||||||
|
|
||||||
|
fun getGlobalScale(): Float {
|
||||||
|
val graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||||
|
val defaultScreenDevice = graphicsEnvironment.defaultScreenDevice
|
||||||
|
val defaultTransform = defaultScreenDevice.defaultConfiguration.defaultTransform
|
||||||
|
return defaultTransform.scaleX.toFloat() // Assuming uniform scaling
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Int.applyUiScale(
|
||||||
|
userUiScale: Float?,
|
||||||
|
systemUiScale: Float = GlobalDensity.density,
|
||||||
|
): Int {
|
||||||
|
if (userUiScale == null) return this
|
||||||
|
return (this * userUiScale / systemUiScale).toInt()
|
||||||
|
}
|
||||||
|
fun Float.applyUiScale(
|
||||||
|
userUiScale: Float?,
|
||||||
|
systemUiScale: Float = GlobalDensity.density,
|
||||||
|
): Float {
|
||||||
|
if (userUiScale == null) return this
|
||||||
|
return (this * userUiScale / systemUiScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Int.unApplyUiScale(
|
||||||
|
userUiScale: Float?,
|
||||||
|
systemUiScale: Float = GlobalDensity.density,
|
||||||
|
): Int {
|
||||||
|
if (userUiScale == null) return this
|
||||||
|
return (this * systemUiScale / userUiScale).toInt()
|
||||||
|
}
|
||||||
|
fun Float.unApplyUiScale(
|
||||||
|
userUiScale: Float?,
|
||||||
|
systemUiScale: Float = GlobalDensity.density,
|
||||||
|
): Float {
|
||||||
|
if (userUiScale == null) return this
|
||||||
|
return (this * systemUiScale / userUiScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DpSize.applyUiScale(
|
||||||
|
userUiScale: Float?,
|
||||||
|
systemUiScale: Float = GlobalDensity.density,
|
||||||
|
): DpSize {
|
||||||
|
if (userUiScale == null) return this
|
||||||
|
if (this == DpSize.Unspecified) return this
|
||||||
|
return DpSize(
|
||||||
|
width = width.let {
|
||||||
|
if (isSpecified) it.value.toInt().applyUiScale(userUiScale, systemUiScale).dp
|
||||||
|
else it
|
||||||
|
},
|
||||||
|
height = height.let {
|
||||||
|
if (isSpecified) it.value.toInt().applyUiScale(userUiScale, systemUiScale).dp
|
||||||
|
else it
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DpSize.unApplyUiScale(
|
||||||
|
userUiScale: Float?,
|
||||||
|
systemUiScale: Float = GlobalDensity.density,
|
||||||
|
): DpSize {
|
||||||
|
if (userUiScale == null) return this
|
||||||
|
if (this == DpSize.Unspecified) return this
|
||||||
|
return DpSize(
|
||||||
|
width = width.let {
|
||||||
|
if (isSpecified) it.value.toInt().unApplyUiScale(userUiScale, systemUiScale).dp
|
||||||
|
else it
|
||||||
|
},
|
||||||
|
height = height.let {
|
||||||
|
if (isSpecified) it.value.toInt().applyUiScale(userUiScale, systemUiScale).dp
|
||||||
|
else it
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
class WindowStateUiScaleAware(
|
||||||
|
private val delegate: WindowState,
|
||||||
|
private val uiScale: Float?,
|
||||||
|
) : WindowState {
|
||||||
|
override var isMinimized: Boolean
|
||||||
|
get() = delegate.isMinimized
|
||||||
|
set(value) {
|
||||||
|
delegate.isMinimized = value
|
||||||
|
}
|
||||||
|
override var placement: WindowPlacement
|
||||||
|
get() = delegate.placement
|
||||||
|
set(value) {
|
||||||
|
delegate.placement = value
|
||||||
|
}
|
||||||
|
override var position: WindowPosition
|
||||||
|
get() = delegate.position
|
||||||
|
set(value) {
|
||||||
|
delegate.position = value
|
||||||
|
}
|
||||||
|
override var size: DpSize
|
||||||
|
get() = run {
|
||||||
|
val s = delegate.size
|
||||||
|
s.applyUiScale(uiScale)
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
delegate.size = value.unApplyUiScale(uiScale)
|
||||||
|
}
|
||||||
|
}*/
|
@ -5,27 +5,27 @@ import kotlinx.serialization.serializer
|
|||||||
|
|
||||||
|
|
||||||
context(Json)
|
context(Json)
|
||||||
inline fun <reified T:Any> MapConfig.putEncoded(key:String, value:T){
|
inline fun <reified T : Any> MapConfig.putEncoded(key: String, value: T) {
|
||||||
putString(key,encodeToString(serializer<T>(),value))
|
putString(key, encodeToString(serializer<T>(), value))
|
||||||
}
|
}
|
||||||
|
|
||||||
context(Json)
|
context(Json)
|
||||||
inline fun <reified T> MapConfig.putEncodedNullable(key: ConfigKey.OfNotPrimitiveType<T>, value:T?){
|
inline fun <reified T> MapConfig.putEncodedNullable(key: ConfigKey.OfNotPrimitiveType<T>, value: T?) {
|
||||||
if (value != null){
|
if (value != null) {
|
||||||
putString(key.keyName,encodeToString(serializer<T>(),value))
|
putString(key.keyName, encodeToString(serializer<T>(), value))
|
||||||
}else{
|
} else {
|
||||||
removeKey(key)
|
removeKey(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context(Json)
|
context(Json)
|
||||||
inline fun <reified T:Any>MapConfig.putEncoded(key: ConfigKey.OfNotPrimitiveType<T>, value: T){
|
inline fun <reified T : Any> MapConfig.putEncoded(key: ConfigKey.OfNotPrimitiveType<T>, value: T) {
|
||||||
putEncoded<T>(key.keyName,value)
|
putEncoded<T>(key.keyName, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
context(Json)
|
context(Json)
|
||||||
inline fun <reified T> MapConfig.getDecoded(key:String):T?{
|
inline fun <reified T> MapConfig.getDecoded(key: String): T? {
|
||||||
val str=getString(key)?:return null
|
val str = getString(key) ?: return null
|
||||||
return runCatching<T> {
|
return runCatching<T> {
|
||||||
decodeFromString(str)
|
decodeFromString(str)
|
||||||
}
|
}
|
||||||
@ -34,7 +34,16 @@ inline fun <reified T> MapConfig.getDecoded(key:String):T?{
|
|||||||
}
|
}
|
||||||
.getOrNull()
|
.getOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
context(Json)
|
context(Json)
|
||||||
inline fun <reified T> MapConfig.getDecoded(key: ConfigKey.OfNotPrimitiveType<T>):T?{
|
inline fun <reified T> MapConfig.getDecoded(key: ConfigKey.OfNotPrimitiveType<T>): T? {
|
||||||
return getDecoded(key.keyName)
|
return getDecoded(key.keyName)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : Any> MapConfig.putNullable(key: ConfigKey.OfPrimitiveType<T>, value: T?) {
|
||||||
|
if (value == null) {
|
||||||
|
removeKey(key)
|
||||||
|
} else {
|
||||||
|
put(key, value)
|
||||||
|
}
|
||||||
}
|
}
|
@ -56,6 +56,7 @@ file=File
|
|||||||
tasks=Tasks
|
tasks=Tasks
|
||||||
tools=Tools
|
tools=Tools
|
||||||
help=Help
|
help=Help
|
||||||
|
system=System
|
||||||
all_finished=All Finished
|
all_finished=All Finished
|
||||||
all_unfinished=All Unfinished
|
all_unfinished=All Unfinished
|
||||||
entire_list=Entire List
|
entire_list=Entire List
|
||||||
@ -194,6 +195,8 @@ settings_use_proxy_describe_system_proxy=System Proxy will be used
|
|||||||
settings_use_proxy_describe_manual_proxy="{{value}}" will be used
|
settings_use_proxy_describe_manual_proxy="{{value}}" will be used
|
||||||
settings_theme=Theme
|
settings_theme=Theme
|
||||||
settings_theme_description=Select a theme for the App
|
settings_theme_description=Select a theme for the App
|
||||||
|
settings_ui_scale=UI Scale
|
||||||
|
settings_ui_scale_description=Adjust the scale of the user interface to make elements larger or smaller
|
||||||
settings_language=Language
|
settings_language=Language
|
||||||
settings_compact_top_bar=Compact Top Bar
|
settings_compact_top_bar=Compact Top Bar
|
||||||
settings_compact_top_bar_description=Merge top bar with title bar when the main window has enough width
|
settings_compact_top_bar_description=Merge top bar with title bar when the main window has enough width
|
||||||
|
Loading…
x
Reference in New Issue
Block a user