I'm trying to figure out if compose-desktop could ...
# compose-desktop
p
I'm trying to figure out if compose-desktop could be a potential replacement for gtk4 in one of my projects. The main use-case i am looking for is themeability. So a user should be able to provide a configuration (could be custom or css or whatever) to theme the used components. A friend that has used compose-desktop before told me that it isn't possible to change style properties at runtime, and this seems like it can't be true.
k
Like a specific button (rollover effect) or the whole app?
Certainly both are possible today, and you can see that in a variety of Compose demos
I don't think you want to change the padding or the insets or anything related to layout, as you don't want things to shift around.
p
please link me a single one, i am struggling to find any examples that would show this
k
What is "this"? Rollover effect?
p
and yes i want to change paddings, margins and all this stuff, it is important for my use-case
"this" is any example that changes a components background color, its padding, margin, border-radius, border size, border-style, background image or anything related to that once the component is clicked
k
You can track rollover with
Copy code
var rollover by remember { mutableStateOf(false) }
And then the
pointerMoveFilter
on your component like
Copy code
.pointerMoveFilter(
    onEnter = {
        rollover = true
        false
    },
    onExit = {
        rollover = false
        false
    },
    onMove = {
        false
    })
and then in your canvas look at the
rollover
value to use a different color
p
so there is no way to say something like
button.style.backgroundColor = Color.red
when it is clicked?
k
It's not css
p
well yeah i know, but it still has to have some properties of what should be rendered
Where the material button colors are queried based on the enabled state
The state-specific colors come from your theme
p
I mean the main use-case is that the style properties are defined externally. Lets say the app loads a config file with a color and i want to use that color then
the stuff i am seing all seems like it is immutable stuff that has to be compiled into the application
c
To my knowledge, pretty much all theming attributes are provided by Ambients, many of which are in the MaterialTheme, so you can customize most of the the theme at runtime by providing new values for those ambients, though I’m not sure how granular you can actually get with those. But you can absolutely change the theme at runtime. Here’s an example showing it being done in an app I’m working on
k
How do you guarantee that the same color is returned every single time you query that "key"?
Compose certainly supports switching the whole "theme" at runtime - in its Material layer
p
yeah i don't want to guarantee that the same color is returned, this is literally the point of that external configuration
@Casey Brooks i am not sure how your example is implemented, but would you be able to read a color from a file and set that as the color?
k
You can get that color from wherever
Even change it on every recomposition
If it causes UI lag because you're hitting disk I/O to read that theme file, that's on you
c
Yup! I currently have it hard-coded to those 4 specific themes, but the selected theme is persisted and re-read on application load. You can definitely read those colors from file to avoid hard-coding themes, allowing the user to specify hex values, etc. Here’s the relevant snippet:
Copy code
class Theme(
    val displayName: String,
    val lightBase: Boolean,
    val primaryColor: Long,
    val secondaryColor: Long,
)

@Composable
fun Theme.useTheme(content: @Composable () -> Unit) {
    MaterialTheme(
        colors = if (lightBase) {
            lightColors(
                primary = Color(primaryColor),
                secondary = Color(secondaryColor),
            )
        } else {
            darkColors(
                primary = Color(primaryColor),
                secondary = Color(secondaryColor),
            )
        }
    ) {
        Surface {
            content()
        }
    }
}