From ef906f06f48afdb8a005af5a2e84fe848eece718 Mon Sep 17 00:00:00 2001 From: per Date: Sun, 27 Sep 2026 16:54:14 +0200 Subject: [PATCH 1/4] prepare v0.4.1 release --- README.md | 16 ++++++++++------ build.gradle | 2 +- gi-common/README.md | 2 +- gi-console/README.md | 12 ++++++------ gi-fx/README.md | 12 ++++++------ gi-swing/README.md | 12 ++++++------ release.md | 14 +++++++++----- 7 files changed, 39 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 405a3ef..ac4d777 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ GuiInteraction enables standalone Groovy applications to have the same user inte ```groovy dependencies { - implementation 'se.alipsa.gi:gi-swing:0.4.0' // or gi-fx, gi-console + implementation 'se.alipsa.gi:gi-swing:0.4.1' // or gi-fx, gi-console } ``` @@ -40,14 +40,14 @@ dependencies { se.alipsa.gi gi-swing - 0.4.0 + 0.4.1 ``` ### Groovy Script with Grape ```groovy -@Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.0') +@Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.1') import se.alipsa.gi.swing.InOut def io = new InOut() @@ -60,10 +60,11 @@ println("File chosen was $file") Scripts can run both in Gade and standalone by checking for the `io` variable: ```groovy +@Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.1') +import se.alipsa.gi.swing.InOut + // This makes the code run equally in Gade and in a standalone Groovy script if (!binding.hasVariable('io')) { - @Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.0') - import se.alipsa.gi.swing.InOut binding.setVariable('io', new InOut()) } @@ -81,6 +82,9 @@ println("File chosen was $file") ## Building from Source +Install a JDK 21 toolchain before building. Gradle uses that toolchain even if +the Gradle daemon runs on a newer JDK. + ```bash ./gradlew build ``` @@ -109,7 +113,7 @@ refresh needs an API key and can be rate limited; it is not a PR gate. Run ## Requirements -- JDK 21 or later +- Java 21 or later to use the published libraries; JDK 21 to build from source - For gi-fx: JDK with JavaFX support (e.g., BellSoft Liberica Full JDK) ## License diff --git a/build.gradle b/build.gradle index 15ed37e..b7fa17f 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ plugins { } group = 'se.alipsa.gi' -version = '0.4.1-SNAPSHOT' +version = '0.4.1' description = 'Allows Gade Gui Interactive capabilities from a standalone app' java { diff --git a/gi-common/README.md b/gi-common/README.md index 7e469d0..7159655 100644 --- a/gi-common/README.md +++ b/gi-common/README.md @@ -37,7 +37,7 @@ See the [API Guide](../docs/API-Guide.md) for detailed usage examples. se.alipsa.gi gi-common - 0.4.0 + 0.4.1 ``` diff --git a/gi-console/README.md b/gi-console/README.md index 7142c98..1c661d0 100644 --- a/gi-console/README.md +++ b/gi-console/README.md @@ -26,7 +26,7 @@ This module provides console-based (text mode) interaction capabilities. It's de ```groovy dependencies { - implementation 'se.alipsa.gi:gi-console:0.4.0' + implementation 'se.alipsa.gi:gi-console:0.4.1' } ``` @@ -36,14 +36,14 @@ dependencies { se.alipsa.gi gi-console - 0.4.0 + 0.4.1 ``` ### Grape (Groovy Script) ```groovy -@Grab(group:'se.alipsa.gi', module:'gi-console', version:'0.4.0') +@Grab(group:'se.alipsa.gi', module:'gi-console', version:'0.4.1') import se.alipsa.gi.console.InOut def io = new InOut() @@ -76,11 +76,11 @@ io.view("

Hello

Welcome!

", "Greeting") ## Fat JAR -A fat JAR (with all dependencies bundled) is available: +A fat JAR bundles runtime dependencies; the consuming application supplies Groovy: ```groovy dependencies { - implementation 'se.alipsa.gi:gi-console:0.4.0:fatjar' + implementation 'se.alipsa.gi:gi-console:0.4.1:fatjar' } ``` @@ -88,7 +88,7 @@ dependencies { - **Clipboard**: Clipboard access is unavailable in headless environments; clipboard methods log the issue and return `null` or no-op. - **Password Input**: Uses masked input through `System.console()` when available. In IDEs and some CI environments, it falls back to visible stdin input and logs a warning. -- **Charts/Images**: `display(Chart)` and `display(File)` for images print a message instead of showing graphics +- **Charts/Images**: chart display prints a message instead of showing graphics; `display(File)` asks the desktop application to open an existing file when the platform supports it - **Swing Components**: `display(JComponent)` is not supported - **File Choosers**: User manually types file paths instead of browsing diff --git a/gi-fx/README.md b/gi-fx/README.md index cd7fc40..7a2e776 100644 --- a/gi-fx/README.md +++ b/gi-fx/README.md @@ -13,7 +13,7 @@ This module provides JavaFX-based dialogs and viewers for user interaction. It o ## Features -- Native JavaFX dialogs for file/directory selection +- JavaFX dialogs for file/directory selection - Rich date and year-month pickers with calendar UI - WebView-based HTML rendering - Markdown viewing with full formatting support @@ -26,7 +26,7 @@ This module provides JavaFX-based dialogs and viewers for user interaction. It o ```groovy dependencies { - implementation 'se.alipsa.gi:gi-fx:0.4.0' + implementation 'se.alipsa.gi:gi-fx:0.4.1' } ``` @@ -36,14 +36,14 @@ dependencies { se.alipsa.gi gi-fx - 0.4.0 + 0.4.1 ``` ### Grape (Groovy Script) ```groovy -@Grab(group:'se.alipsa.gi', module:'gi-fx', version:'0.4.0') +@Grab(group:'se.alipsa.gi', module:'gi-fx', version:'0.4.1') import se.alipsa.gi.fx.InOut def io = new InOut() @@ -71,11 +71,11 @@ io.viewMarkdown("# Title\n\nSome **bold** text", "Document") ## Fat JAR -A fat JAR (with all dependencies bundled) is available: +A fat JAR bundles runtime dependencies; the consuming application supplies Groovy and JavaFX: ```groovy dependencies { - implementation 'se.alipsa.gi:gi-fx:0.4.0:fatjar' + implementation 'se.alipsa.gi:gi-fx:0.4.1:fatjar' } ``` diff --git a/gi-swing/README.md b/gi-swing/README.md index 44edd58..80290df 100644 --- a/gi-swing/README.md +++ b/gi-swing/README.md @@ -13,7 +13,7 @@ This module provides Swing-based dialogs and viewers for user interaction. It wo ## Features - Standard Swing file and directory choosers -- Date and year-month pickers (via LGoodDatePicker) +- Date pickers via LGoodDatePicker and year-month pickers via swing-yearmonth-picker - HTML viewing via JEditorPane - Table display with JTable - Clipboard operations @@ -26,7 +26,7 @@ This module provides Swing-based dialogs and viewers for user interaction. It wo ```groovy dependencies { - implementation 'se.alipsa.gi:gi-swing:0.4.0' + implementation 'se.alipsa.gi:gi-swing:0.4.1' } ``` @@ -36,14 +36,14 @@ dependencies { se.alipsa.gi gi-swing - 0.4.0 + 0.4.1 ``` ### Grape (Groovy Script) ```groovy -@Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.0') +@Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.1') import se.alipsa.gi.swing.InOut def io = new InOut() @@ -75,11 +75,11 @@ io.view([ ## Fat JAR -A fat JAR (with all dependencies bundled) is available: +A fat JAR bundles runtime dependencies; the consuming application supplies Groovy: ```groovy dependencies { - implementation 'se.alipsa.gi:gi-swing:0.4.0:fatjar' + implementation 'se.alipsa.gi:gi-swing:0.4.1:fatjar' } ``` diff --git a/release.md b/release.md index 8d2e37f..b719255 100644 --- a/release.md +++ b/release.md @@ -1,14 +1,16 @@ # Gui Interaction Release Notes ## Unreleased + +## 0.4.1 - 2026-09-27 - Fixed (build): pin Java 21 toolchains in all modules; run Spotless and SpotBugs in default builds; scan all modules with `dependencyCheckAggregate`. -- Fixed (build): select JavaFX natives for the Gradle JVM's OS and architecture; unsupported combinations fail when JavaFX dependencies resolve, leaving unrelated tasks available. -- Fixed: console null file names and password EOF no longer throw; null matrix views are guarded and unnamed JavaFX tables use `Table` as their title. +- Fixed (build): select JavaFX natives for the host OS and Java 21 toolchain architecture; unsupported combinations fail when JavaFX dependencies resolve, leaving unrelated tasks available. +- Fixed: console null file names and password EOF no longer throw; null matrix views are guarded and unnamed Swing and JavaFX tables use `Table` as their title. - Fixed: JavaFX copy shortcut detection uses locale-independent casing, and the redundant `rowsForViewer` helper was removed. - Fixed (packaging): merge duplicate licence, notice, and dependency metadata in fat JARs. - Fixed (release): promote curated Unreleased notes, preserve backslashes in commit subjects, handle release retries, and validate version shapes before mutating files. -- Added: debug diagnostics for `urlExists` failures and Windows shell branch coverage with a CI smoke job. -- Build: upgraded Groovy to 5.1.3, Matrix BOM to 2.6.0, CommonMark to 0.30.0, jsoup to 1.23.2, JUnit to 6.1.3, Gradle Versions to 0.64.0, Spotless to 8.10.2, and SpotBugs (plugin/engine) to 6.5.11/4.10.4. +- Added: `urlExists` warnings for unsupported schemes and broken redirects, with debug diagnostics for connection and HTTP failures. Logged URLs redact credentials, including malformed URL paths. +- Build: upgraded Groovy to 5.1.3, Matrix BOM to 2.6.0, CommonMark to 0.30.0, jsoup to 1.23.2, JUnit to 6.1.3, Gradle Versions to 0.64.0, Spotless to 8.10.3, and SpotBugs (plugin/engine) to 6.5.12/4.10.4. - Common: added `sh` and `shell` methods for executing platform shell commands. `sh` returns captured standard output and can stream output while the command runs; `shell` returns a `ShellResult` containing standard output, standard error, exit code, and success status. Both support optional timeouts. These methods execute arbitrary commands and should not receive untrusted input. - Breaking (packaging): fat JARs are now built with GradleUp Shadow via the `shadowJar` task instead of a hand-rolled `fatJar` task. The published artifact name is unchanged (`--fatjar.jar`), but the Gradle task is now `shadowJar`. - Fixed: fat JARs dropped all but the first copy of each `META-INF/services` entry, disabling most ph-css/gsvg service registrations and part of Tika's. Service files are now merged. @@ -25,10 +27,12 @@ - Fixed: console `display(File)` called `Desktop.open` without checking that the OPEN action is supported, and threw on a null file. Both are now reported on stdout. - Fixed: console input now honors `stdin.encoding` (JDK 25+) or the platform console's charset (JDK 17+) instead of always using the JVM default. - Fixed: `saveToClipboard(File)` wrote `Lost ownership` to stdout when clipboard ownership changed. -- Build: CI now runs `./gradlew check --no-configuration-cache`, which is the only invocation under which Spotless and SpotBugs are applied. The scheduled dependency-check job is reachable again. +- Build: CI builds and tests all modules on Linux and Windows, including Spotless and SpotBugs. The dependency-check job runs on a schedule or by manual dispatch. - Build: `release.sh` verifies the version was actually written to `build.gradle`, names the modules already published when a release fails partway, validates/explicitly confirms `--skip ` before resuming without re-publishing them, and rejects `--skip` with `--bump`. - Fixed: publishing `gi-console`, `gi-fx`, or `gi-swing` failed with "multiple artifacts with the identical extension and classifier" because the Shadow migration both declared the fat-jar artifact explicitly and let Shadow's own publication variant add it. The explicit declaration is removed; Shadow's variant is sufficient. - Fixed: fat jars now also merge `META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule`, so bundling multiple Groovy extension-module jars (e.g. `matrix-core` and `matrix-groovy-ext`) no longer silently hides one's extension methods behind the other's. +- Fixed (release): choose the newest installed JavaFX-capable SDKMAN JDK 21 when several versions are available. +- Fixed (test): load the Swing HTML page test from a stable fixture so Windows can complete it without a temporary-file deletion race. ## 0.4.0 - 2026-08-03 - Breaking: `FileUtils.getResourceUrl` returns `null` for paths that do not exist; use `File` for output targets that will be created later. From be83b22bbd0bc9155b9f8d7c5a08a4cfde2ac321 Mon Sep 17 00:00:00 2001 From: per Date: Sun, 27 Sep 2026 17:43:12 +0200 Subject: [PATCH 2/4] correct v0.4.1 release examples --- README.md | 4 ++-- docs/API-Guide.md | 9 +++++---- docs/DEPENDENCIES.md | 15 ++++++++------- docs/PUBLISHING.md | 5 ++++- gi-console/README.md | 2 +- gi-fx/README.md | 2 +- gi-swing/README.md | 7 +++---- release.md | 2 +- 8 files changed, 25 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index ac4d777..fd38ec0 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ dependencies { ### Groovy Script with Grape ```groovy -@Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.1') +@Grab('se.alipsa.gi:gi-swing:0.4.1') import se.alipsa.gi.swing.InOut def io = new InOut() @@ -60,7 +60,7 @@ println("File chosen was $file") Scripts can run both in Gade and standalone by checking for the `io` variable: ```groovy -@Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.1') +@Grab('se.alipsa.gi:gi-swing:0.4.1') import se.alipsa.gi.swing.InOut // This makes the code run equally in Gade and in a standalone Groovy script diff --git a/docs/API-Guide.md b/docs/API-Guide.md index 395fefa..2efae4a 100644 --- a/docs/API-Guide.md +++ b/docs/API-Guide.md @@ -16,7 +16,7 @@ This guide provides usage examples for the GuiInteraction library. ```groovy // Using Grape for dependency resolution -@Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.0') +@Grab('se.alipsa.gi:gi-swing:0.4.1') import se.alipsa.gi.swing.InOut def io = new InOut() @@ -26,7 +26,7 @@ Or in your `build.gradle`: ```groovy dependencies { - implementation 'se.alipsa.gi:gi-swing:0.4.0' + implementation 'se.alipsa.gi:gi-swing:0.4.1' } ``` @@ -329,10 +329,11 @@ assert FileUtils.baseName("/tmp/report#2.pdf") == "report#2.pdf" The library is designed to be compatible with [Gade](https://github.com/Alipsa/gade). Scripts can detect the environment: ```groovy +@Grab('se.alipsa.gi:gi-swing:0.4.1') +import se.alipsa.gi.swing.InOut + // Check if running in Gade or standalone if (!binding.hasVariable('io')) { - @Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.0') - import se.alipsa.gi.swing.InOut binding.setVariable('io', new InOut()) } diff --git a/docs/DEPENDENCIES.md b/docs/DEPENDENCIES.md index a944c41..2f823f1 100644 --- a/docs/DEPENDENCIES.md +++ b/docs/DEPENDENCIES.md @@ -18,8 +18,8 @@ The core module includes these key dependencies: ### gi-fx, gi-swing, gi-console UI modules add minimal additional dependencies: -- **gi-fx**: JavaFX (provided by JVM), YearMonthPicker -- **gi-swing**: Batik (SVG), LGoodDatePicker, Swing YearMonthPicker +- **gi-fx**: JavaFX (supplied by the JDK or consumer), fx-yearmonth-picker +- **gi-swing**: Matrix Charts (SVG rendering), swing-widgets (date and year-month pickers) - **gi-console**: JSoup (HTML parsing) ## Apache Tika Dependency Impact @@ -49,9 +49,9 @@ PDFs or Office documents), add the full parser package: ```groovy dependencies { - implementation 'se.alipsa.gi:gi-common:0.4.0' + implementation 'se.alipsa.gi:gi-common:0.4.1' // Add full Tika parsers for document content extraction - implementation 'org.apache.tika:tika-parsers-standard-package:3.2.3' + implementation 'org.apache.tika:tika-parsers-standard-package:3.3.2' } ``` @@ -64,11 +64,12 @@ This adds support for: ### Fat JAR for Standalone Scripts -The fat JARs (`gi-swing-fatjar`, `gi-fx-fatjar`, etc.) include all dependencies -and are designed for standalone Groovy scripts: +The fat JAR artifacts bundle runtime dependencies but exclude Groovy, which the +consuming application must supply. `gi-fx` also needs JavaFX at runtime, either +from the JDK or as separate dependencies. The artifact classifier is `fatjar`: ```groovy -@Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.0', classifier:'fatjar') +@Grab(group='se.alipsa.gi', module='gi-swing', version='0.4.1', classifier='fatjar') import se.alipsa.gi.swing.InOut ``` diff --git a/docs/PUBLISHING.md b/docs/PUBLISHING.md index 50a82a2..26167b1 100644 --- a/docs/PUBLISHING.md +++ b/docs/PUBLISHING.md @@ -189,7 +189,7 @@ After releasing: - [ ] Push tag: `git push origin vX.Y.Z` - [ ] Create GitHub release: https://github.com/Alipsa/GuiInteraction/releases/new - [ ] Verify on Maven Central (may take 10-30 minutes): https://central.sonatype.com/search?q=se.alipsa.gi -- [ ] Bump version to next SNAPSHOT for development +- [ ] Immediately bump version to the next SNAPSHOT for development before other changes land on main ## Troubleshooting @@ -285,6 +285,9 @@ script generates notes from commit subjects. Both paths are idempotent for a version already in the changelog, so `--skip` retries do not duplicate notes. If a retry finds additional curated notes under `## Unreleased`, the script warns that they are not included in the already-recorded version. +If `release.md` already has a dated heading for the version, the script leaves +that date unchanged. Check it against the actual publication date and re-date +the heading before running a delayed release. Commit curated notes before running `release.sh`: every release path requires `release.md` to be clean. SNAPSHOT and `--bump` releases also require clean diff --git a/gi-console/README.md b/gi-console/README.md index 1c661d0..7b0b98c 100644 --- a/gi-console/README.md +++ b/gi-console/README.md @@ -43,7 +43,7 @@ dependencies { ### Grape (Groovy Script) ```groovy -@Grab(group:'se.alipsa.gi', module:'gi-console', version:'0.4.1') +@Grab('se.alipsa.gi:gi-console:0.4.1') import se.alipsa.gi.console.InOut def io = new InOut() diff --git a/gi-fx/README.md b/gi-fx/README.md index 7a2e776..fb35b79 100644 --- a/gi-fx/README.md +++ b/gi-fx/README.md @@ -43,7 +43,7 @@ dependencies { ### Grape (Groovy Script) ```groovy -@Grab(group:'se.alipsa.gi', module:'gi-fx', version:'0.4.1') +@Grab('se.alipsa.gi:gi-fx:0.4.1') import se.alipsa.gi.fx.InOut def io = new InOut() diff --git a/gi-swing/README.md b/gi-swing/README.md index 80290df..9564eac 100644 --- a/gi-swing/README.md +++ b/gi-swing/README.md @@ -13,7 +13,7 @@ This module provides Swing-based dialogs and viewers for user interaction. It wo ## Features - Standard Swing file and directory choosers -- Date pickers via LGoodDatePicker and year-month pickers via swing-yearmonth-picker +- Date and year-month pickers via `se.alipsa:swing-widgets` - HTML viewing via JEditorPane - Table display with JTable - Clipboard operations @@ -43,7 +43,7 @@ dependencies { ### Grape (Groovy Script) ```groovy -@Grab(group:'se.alipsa.gi', module:'gi-swing', version:'0.4.1') +@Grab('se.alipsa.gi:gi-swing:0.4.1') import se.alipsa.gi.swing.InOut def io = new InOut() @@ -89,8 +89,7 @@ dependencies { ## Dependencies -- [LGoodDatePicker](https://github.com/LGoodDatePicker/LGoodDatePicker) - Date picker component -- [swing-yearmonth-picker](https://github.com/Alipsa/swing-yearmonth-picker) - Year-month picker +- `se.alipsa:swing-widgets` - Date and year-month picker components ## API Documentation diff --git a/release.md b/release.md index b719255..c8dc90a 100644 --- a/release.md +++ b/release.md @@ -9,7 +9,7 @@ - Fixed: JavaFX copy shortcut detection uses locale-independent casing, and the redundant `rowsForViewer` helper was removed. - Fixed (packaging): merge duplicate licence, notice, and dependency metadata in fat JARs. - Fixed (release): promote curated Unreleased notes, preserve backslashes in commit subjects, handle release retries, and validate version shapes before mutating files. -- Added: `urlExists` warnings for unsupported schemes and broken redirects, with debug diagnostics for connection and HTTP failures. Logged URLs redact credentials, including malformed URL paths. +- Added: `urlExists` warnings for unsupported schemes and broken redirects, with debug diagnostics for connection and HTTP failures. Logged URLs redact credentials, including malformed URL paths. Windows shell execution now has integration test coverage. - Build: upgraded Groovy to 5.1.3, Matrix BOM to 2.6.0, CommonMark to 0.30.0, jsoup to 1.23.2, JUnit to 6.1.3, Gradle Versions to 0.64.0, Spotless to 8.10.3, and SpotBugs (plugin/engine) to 6.5.12/4.10.4. - Common: added `sh` and `shell` methods for executing platform shell commands. `sh` returns captured standard output and can stream output while the command runs; `shell` returns a `ShellResult` containing standard output, standard error, exit code, and success status. Both support optional timeouts. These methods execute arbitrary commands and should not receive untrusted input. - Breaking (packaging): fat JARs are now built with GradleUp Shadow via the `shadowJar` task instead of a hand-rolled `fatJar` task. The published artifact name is unchanged (`--fatjar.jar`), but the Gradle task is now `shadowJar`. From 7b18e83389e01573d68d115e7b2561b0e41d75c7 Mon Sep 17 00:00:00 2001 From: per Date: Sun, 27 Sep 2026 18:00:29 +0200 Subject: [PATCH 3/4] refine v0.4.1 release guidance --- README.md | 10 ++++++---- docs/API-Guide.md | 10 ++++++---- docs/DEPENDENCIES.md | 7 ++++--- release.md | 3 ++- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index fd38ec0..b5f656b 100644 --- a/README.md +++ b/README.md @@ -57,15 +57,17 @@ println("File chosen was $file") ## Gade Compatibility -Scripts can run both in Gade and standalone by checking for the `io` variable: +Scripts can run both in Gade and standalone by checking for the `io` variable. +The dependency is loaded only when Gade has not already supplied `io`: ```groovy -@Grab('se.alipsa.gi:gi-swing:0.4.1') -import se.alipsa.gi.swing.InOut +import static groovy.grape.Grape.grab // This makes the code run equally in Gade and in a standalone Groovy script if (!binding.hasVariable('io')) { - binding.setVariable('io', new InOut()) + grab(group: 'se.alipsa.gi', module: 'gi-swing', version: '0.4.1') + def inOutClass = this.class.classLoader.loadClass('se.alipsa.gi.swing.InOut') + binding.setVariable('io', inOutClass.getDeclaredConstructor().newInstance()) } def file = io.chooseFile("Choose a file", ".", "Pick a file please!") diff --git a/docs/API-Guide.md b/docs/API-Guide.md index 2efae4a..efbbb28 100644 --- a/docs/API-Guide.md +++ b/docs/API-Guide.md @@ -326,15 +326,17 @@ assert FileUtils.baseName("/tmp/report#2.pdf") == "report#2.pdf" ## Gade Compatibility -The library is designed to be compatible with [Gade](https://github.com/Alipsa/gade). Scripts can detect the environment: +The library is designed to be compatible with [Gade](https://github.com/Alipsa/gade). +Scripts can detect the environment and load gi-swing only when `io` is absent: ```groovy -@Grab('se.alipsa.gi:gi-swing:0.4.1') -import se.alipsa.gi.swing.InOut +import static groovy.grape.Grape.grab // Check if running in Gade or standalone if (!binding.hasVariable('io')) { - binding.setVariable('io', new InOut()) + grab(group: 'se.alipsa.gi', module: 'gi-swing', version: '0.4.1') + def inOutClass = this.class.classLoader.loadClass('se.alipsa.gi.swing.InOut') + binding.setVariable('io', inOutClass.getDeclaredConstructor().newInstance()) } // Now 'io' works the same in both Gade and standalone diff --git a/docs/DEPENDENCIES.md b/docs/DEPENDENCIES.md index 2f823f1..82984a7 100644 --- a/docs/DEPENDENCIES.md +++ b/docs/DEPENDENCIES.md @@ -19,7 +19,7 @@ The core module includes these key dependencies: UI modules add minimal additional dependencies: - **gi-fx**: JavaFX (supplied by the JDK or consumer), fx-yearmonth-picker -- **gi-swing**: Matrix Charts (SVG rendering), swing-widgets (date and year-month pickers) +- **gi-swing**: swing-widgets (date and year-month pickers); SVG rendering uses Matrix Charts from `gi-common` - **gi-console**: JSoup (HTML parsing) ## Apache Tika Dependency Impact @@ -66,10 +66,11 @@ This adds support for: The fat JAR artifacts bundle runtime dependencies but exclude Groovy, which the consuming application must supply. `gi-fx` also needs JavaFX at runtime, either -from the JDK or as separate dependencies. The artifact classifier is `fatjar`: +from the JDK or as separate dependencies. The artifact classifier is `fatjar`; +disable transitive resolution to avoid loading separate copies of bundled dependencies: ```groovy -@Grab(group='se.alipsa.gi', module='gi-swing', version='0.4.1', classifier='fatjar') +@Grab(group='se.alipsa.gi', module='gi-swing', version='0.4.1', classifier='fatjar', transitive=false) import se.alipsa.gi.swing.InOut ``` diff --git a/release.md b/release.md index c8dc90a..d23d5cd 100644 --- a/release.md +++ b/release.md @@ -9,7 +9,8 @@ - Fixed: JavaFX copy shortcut detection uses locale-independent casing, and the redundant `rowsForViewer` helper was removed. - Fixed (packaging): merge duplicate licence, notice, and dependency metadata in fat JARs. - Fixed (release): promote curated Unreleased notes, preserve backslashes in commit subjects, handle release retries, and validate version shapes before mutating files. -- Added: `urlExists` warnings for unsupported schemes and broken redirects, with debug diagnostics for connection and HTTP failures. Logged URLs redact credentials, including malformed URL paths. Windows shell execution now has integration test coverage. +- Added: `urlExists` warnings for unsupported schemes and broken redirects, with debug diagnostics for connection and HTTP failures. Logged URLs redact credentials, including malformed URL paths. +- Added (test): Windows shell execution integration coverage. - Build: upgraded Groovy to 5.1.3, Matrix BOM to 2.6.0, CommonMark to 0.30.0, jsoup to 1.23.2, JUnit to 6.1.3, Gradle Versions to 0.64.0, Spotless to 8.10.3, and SpotBugs (plugin/engine) to 6.5.12/4.10.4. - Common: added `sh` and `shell` methods for executing platform shell commands. `sh` returns captured standard output and can stream output while the command runs; `shell` returns a `ShellResult` containing standard output, standard error, exit code, and success status. Both support optional timeouts. These methods execute arbitrary commands and should not receive untrusted input. - Breaking (packaging): fat JARs are now built with GradleUp Shadow via the `shadowJar` task instead of a hand-rolled `fatJar` task. The published artifact name is unchanged (`--fatjar.jar`), but the Gradle task is now `shadowJar`. From b6fc3e2fcf7621b4d1980f79b84f22595533f70e Mon Sep 17 00:00:00 2001 From: per Date: Sun, 27 Sep 2026 22:02:34 +0200 Subject: [PATCH 4/4] preserve Swing constructor errors in examples --- README.md | 2 +- docs/API-Guide.md | 2 +- gi-swing/test.gsh | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b5f656b..2768052 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ import static groovy.grape.Grape.grab if (!binding.hasVariable('io')) { grab(group: 'se.alipsa.gi', module: 'gi-swing', version: '0.4.1') def inOutClass = this.class.classLoader.loadClass('se.alipsa.gi.swing.InOut') - binding.setVariable('io', inOutClass.getDeclaredConstructor().newInstance()) + binding.setVariable('io', inOutClass.newInstance()) } def file = io.chooseFile("Choose a file", ".", "Pick a file please!") diff --git a/docs/API-Guide.md b/docs/API-Guide.md index efbbb28..6e640bb 100644 --- a/docs/API-Guide.md +++ b/docs/API-Guide.md @@ -336,7 +336,7 @@ import static groovy.grape.Grape.grab if (!binding.hasVariable('io')) { grab(group: 'se.alipsa.gi', module: 'gi-swing', version: '0.4.1') def inOutClass = this.class.classLoader.loadClass('se.alipsa.gi.swing.InOut') - binding.setVariable('io', inOutClass.getDeclaredConstructor().newInstance()) + binding.setVariable('io', inOutClass.newInstance()) } // Now 'io' works the same in both Gade and standalone diff --git a/gi-swing/test.gsh b/gi-swing/test.gsh index fe82c63..4c4406c 100644 --- a/gi-swing/test.gsh +++ b/gi-swing/test.gsh @@ -2,8 +2,8 @@ import static groovy.grape.Grape.grab if (! binding.hasVariable('io')) { grab(group:"se.alipsa.gi", module: "gi-swing", version:"0.4.0") - binding.setVariable('io', this.class.classLoader.loadClass("se.alipsa.gi.swing.InOut").getDeclaredConstructor().newInstance()) + binding.setVariable('io', this.class.classLoader.loadClass("se.alipsa.gi.swing.InOut").newInstance()) } def file = io.chooseFile("Choose a file", ".", "Pick a file please!" ) -println("File chosen was $file") \ No newline at end of file +println("File chosen was $file")