mig and other goodies

This commit is contained in:
2025-07-15 02:04:27 +00:00
parent 092986b351
commit 1bb524646e
6 changed files with 170 additions and 7 deletions

View File

@@ -1,24 +1,27 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
kotlin("jvm") version "2.1.10"
kotlin("jvm") version "2.2.0"
`maven-publish` // for publishToMavenLocal
id("org.jetbrains.dokka-javadoc") version "2.0.0"
}
group = "net.eksb"
dependencies {}
dependencies {
api("com.miglayout:miglayout-swing:11.4.2")
}
java {
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_17
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
withSourcesJar()
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
jvmTarget.set(JvmTarget.JVM_21)
}
}

View File

@@ -0,0 +1,13 @@
package net.eksb.kswingutil
import javax.swing.UIManager
fun systemLookAndFeel() {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName()
)
} catch ( e:java.lang.Exception) {
System.err.println( "Error setting laf: ${e.message}" )
}
}

View File

@@ -2,7 +2,10 @@ package net.eksb.kswingutil.ext
import net.eksb.kswingutil.property.MutableProperty
import net.eksb.kswingutil.property.Property
import java.awt.Color
import java.awt.Component
import javax.swing.JComponent
import javax.swing.border.Border
/**
* One-way bind a [java.awt.Component] to a [Property].
@@ -82,4 +85,22 @@ fun <T> Component.bind(
// initialize component with the property's value
propertyToComponent()
}
}
fun JComponent.bindTooltipText(property:Property<String>) {
bind(property) {
toolTipText = it
}
}
fun JComponent.bindBackground(property:Property<Color>) {
bind(property) {
background = it
}
}
fun JComponent.bindBorder(property:Property<Border>) {
bind(property) {
border = it
}
}

View File

@@ -5,6 +5,9 @@ import net.eksb.kswingutil.property.Property
import net.eksb.kswingutil.ext.bind
import java.awt.Component
import java.awt.Container
import java.awt.Font
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import javax.swing.BorderFactory
import javax.swing.Box
import javax.swing.DefaultComboBoxModel
@@ -87,3 +90,30 @@ fun <T> JComboBox<T>.bind(property:MutableProperty<T>) {
fun Container.button(constraints:Any?=null, text:String?=null, block:JButton.()->Unit = {}):JButton = add(constraints,
JButton(text),block)
fun JComponent.onHover(
enter:(MouseEvent)->Unit,
exit:(MouseEvent)->Unit
) {
addMouseListener(object: MouseAdapter() {
override fun mouseEntered(e: MouseEvent) {
enter.invoke(e)
}
override fun mouseExited(e: MouseEvent) {
exit.invoke(e)
}
})
}
fun JComponent.hoverProperty(): Property<Boolean> =
MutableProperty(false).apply {
onHover(
enter = { e -> value = true },
exit = { e -> value = false }
)
}
fun JComponent.bold() {
font = font.deriveFont(Font.BOLD)
repaint()
}

View File

@@ -0,0 +1,74 @@
package net.eksb.kswingutil.mig
// Utility and extension functions for using MigLayout. See http://miglayout.com/
import java.awt.Container
import java.util.UUID
import net.miginfocom.swing.*
// Let users import net.eksb.kswingutil.mig.* and not have to also import net.miginfocom.layout.*
typealias LC = net.miginfocom.layout.LC
typealias AC = net.miginfocom.layout.AC
typealias CC = net.miginfocom.layout.CC
fun Container.migLayout(
layoutConstraints:LC?=null,
colConstraints:AC?=null,
rowConstraints:AC?=null
) {
layout = MigLayout(
( layoutConstraints ?: LC() ).debugIfEnv(),
colConstraints ?: AC(),
rowConstraints ?: AC() )
}
fun CC.heightMin():CC = height("min")
/**
* Set a cell to take up the full height of the row
* without impacting the height of the row.
* Or, in other words, to take the full height of the tallest cell
* besides this one.
*/
fun CC.heightGrowMin():CC = growY().heightMin()
fun AC.grow(w:Int) = grow(w.toFloat())
fun AC.grow(w:Double) = grow(w.toFloat())
/**
* Set all columns to be the same width.
*
* This works by setting [AC.sizeGroup] to the same thing
* for all columns.
*
* After this method returns, the end, [AC.curIx] is the last index.
*/
fun AC.allColsSameWidth():AC = apply {
val group = UUID.randomUUID().toString()
(0 until count).forEach { index ->
index(index).sizeGroup(group)
}
}
fun AC.alignRight() = align("right")
fun CC.alignRight() = alignX("right")
fun AC.alignLeft() = align("left")
fun CC.alignLeft() = alignX("left")
fun AC.alignCenter() = align("center")
fun CC.alignCenter() = alignX("center")
private val debug:Boolean = System.getenv("SWINGUTIL_MIG_DEBUG")?.toBoolean() == true
/**
* Show debug decorations if $SWINGUTIL_MIG_DEBUG is set to "true"
* @param repaintMillis The new debug repaint interval.
*/
fun LC.debugIfEnv(repaintMillis:Int=300):LC = apply {
if ( debug ) {
debug(repaintMillis)
}
}
fun LC.noInsets() = insetsAll("0")
fun LC.noGridGap() = gridGap("0","0")

View File

@@ -14,4 +14,26 @@ fun <T,R> Property<T>.map(transform:(T)->R):Property<R> =
/**
* Get a [Property] that is true when this property is not null.
*/
fun <T> Property<T>.mapNotNull():Property<Boolean> = map { it != null }
fun <T> Property<T>.mapNotNull():Property<Boolean> = map { it != null }
/**
* Create a Property<T> that is updated to the value generated by [op]
* when any of the supplied [props] change.
*
* @param props Update this property when any of these properties change.
* @param op Calculates the value of this property
*/
fun <T> propertyFrom(vararg props:Property<*>, op:()->T): Property<T> =
MutableProperty(op())
.apply {
props.forEach { prop ->
prop.addListener { _, _ ->
value = op()
}
}
}
/**
* Get a `Property<Boolean>` that is `!this.value`.
*/
operator fun Property<Boolean>.not():Property<Boolean> = map { ! it }