uranium-swing is a Kotlin library allowing you to create Swing-based desktop applications using a concise DSL in React way. For more details how the uranium library works, visit the Uranium page.
uranium-swing is located in jCenter, you can add it as a dependency to your Gradle or Maven project.
Gradle (Kotlin DSL):
dependencies {
implementation("pl.karol202.uranium.swing:uranium-swing:0.2.2")
}
Gradle (Groovy):
dependencies {
implementation "pl.karol202.uranium.swing:uranium-swing:0.2.2"
}
Maven:
<dependency>
<groupId>pl.karol202.uranium.swing</groupId>
<artifactId>uranium-swing</artifactId>
<version>0.2.2</version>
</dependency>
Make sure that you have jCenter in your repositories
section:
repositories {
jcenter()
}
Swing like many other UI libraries is based on the imperative paradigm. That means, that in order to have layout, first you have to create a container, then create components and then add the components to container. Thing can get messy, when your layouts are nested. More problems arises, when it comes to state management.
With Uranium instead of writing such code:
class NamePanel(initialName: String) : JPanel(), ActionListener
{
private lateinit var textField: JTextField
private lateinit var label: JLabel
init
{
layout = BoxLayout(this, BoxLayout.Y_AXIS)
val label = JLabel()
val textField = JTextField(createText(initialName))
textField.addActionListener(this)
add(label)
add(textField)
}
override fun actionPerformed(e: ActionEvent?)
{
label.text = createText(textField.text)
}
private fun createText(text: String) = "Hello, $text"
}
you can write:
class NameComponent(props: Props) : SwingAbstractAppComponent<NameComponent.Props>(props),
UStateful<NameComponent.State>
{
data class Props(override val key: Any,
val initialName: String) : UProps
data class State(val name: String) : UState
override var state by state(State(props.initialName))
override fun SwingRenderScope.render() = boxLayout(axis = BoxAxis.Y) {
+ textField()
.text(state.name)
.onTextChange(::setName)
+ label()
.text("Hello, ${state.name}")
}
private fun setName(text: String) = setState { copy(name = text) }
}
The latter one is much more convenient, scalable and easy to manage when it comes to state management (thanks to the unidirectional data flow).
During the development of this project a lot of design flaws and inconsistent behaviours of Swing has been discovered, so I'm not sure whether this library should be still developed. Probably no further features will have been introduced and only little improvements and bug fixes will be done.
Contributions are highly welcome.
If you find a bug or would like have some feature implemented, file an issue. You can also create a pull request if you have working solution for some issue.