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 import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins { plugins {
kotlin("jvm") version "2.1.10" kotlin("jvm") version "2.2.0"
`maven-publish` // for publishToMavenLocal `maven-publish` // for publishToMavenLocal
id("org.jetbrains.dokka-javadoc") version "2.0.0" id("org.jetbrains.dokka-javadoc") version "2.0.0"
} }
group = "net.eksb" group = "net.eksb"
dependencies {} dependencies {
api("com.miglayout:miglayout-swing:11.4.2")
}
java { java {
targetCompatibility = JavaVersion.VERSION_17 toolchain {
sourceCompatibility = JavaVersion.VERSION_17 languageVersion.set(JavaLanguageVersion.of(21))
}
withSourcesJar() withSourcesJar()
} }
kotlin { kotlin {
compilerOptions { 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.MutableProperty
import net.eksb.kswingutil.property.Property import net.eksb.kswingutil.property.Property
import java.awt.Color
import java.awt.Component import java.awt.Component
import javax.swing.JComponent
import javax.swing.border.Border
/** /**
* One-way bind a [java.awt.Component] to a [Property]. * One-way bind a [java.awt.Component] to a [Property].
@@ -83,3 +86,21 @@ fun <T> Component.bind(
// initialize component with the property's value // initialize component with the property's value
propertyToComponent() 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 net.eksb.kswingutil.ext.bind
import java.awt.Component import java.awt.Component
import java.awt.Container 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.BorderFactory
import javax.swing.Box import javax.swing.Box
import javax.swing.DefaultComboBoxModel 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, fun Container.button(constraints:Any?=null, text:String?=null, block:JButton.()->Unit = {}):JButton = add(constraints,
JButton(text),block) 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

@@ -15,3 +15,25 @@ fun <T,R> Property<T>.map(transform:(T)->R):Property<R> =
* Get a [Property] that is true when this property is not null. * 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 }