swing-extras Release Notes
Author: Steve Corbett

Version 2.7.0 [2026-01-25] - Maintenance release
  #317 - FormPanel: help labels can now be toggled dynamically
  #315 - Bug: KeyStrokeManager.clear() was not removing accelerators
  #314 - AboutPanel: double-click memory label to trigger GC
  #308 - Bug: ImageTextUtil.drawText() now uses adjusted line length
  #307 - Bug: ImagePanel was doubling mouse events for animated GIFs
  #305 - ImagePanel: add dispose() method to prevent memory leaks
  #301 - ImageListPanel: fix setBackground() behavior
  #299 - New ListField support class: ListItemSelectAllAction
  #297 - ListField: minor API tweak
  #293 - KeyStrokeManager: minor API improvements
  #289 - DirTree: add listener notification for hidden file toggle
  #287 - MultiProgressDialog: make label truncation configurable
  #284 - Refactor resource handling in swing-forms
  #276 - MultiProgressDialog: make progress label configurable
  #275 - Fix intermittent bug in SingleInstanceManager test
  #273 - Added KeyStrokeField and KeyStrokeProperty
  #267 - MessageUtil: add more convenience wrappers for JOptionPane
  #264 - ListSubsetField: fire value changed events when items move
  #257 - new FileSystemUtil method: getUniqueDestinationFile()
  #256 - DirTree: remove Linux-specific logic
  #253 - ImagePanel: allow custom border to be set
  #252 - ImageUtil: better validation in loadImageIcon
  #251 - CoalescingDocumentListener has failed me for the last time
  #250 - AbstractProperty: add margin padding options
  #249 - New visual effects: FadeLayerUI, BlurLayerUI, SnowLayerUI
  #248 - ListField: offer built-in helper actions for common tasks
  #247 - DirTree: add selectionWillChange event with veto option
  #246 - Utility classes: remove final modifiers where not needed
  #245 - ListField: listener convenience methods; better javadoc
  #244 - LabelProperty: add ability to set field label text
  #243 - New utility class: ResourceLoader
  #242 - Added more VersionStringComparator convenience methods
  #241 - Mention the swing-extras archetype in the README
  #240 - ListField: add support for action buttons
  #239 - PropertiesManager: add option to set border margin
  #238 - EnumProperty: remove useNamesInsteadOfLabels option
  #237 - FormPanel: minor refactoring and Javadoc touchups
  #232 - DirTree: add option to show hidden files
  #231 - Progress package: Javadoc pass and minor touchups
  #230 - DirTree: mark factory methods as deprecated
  #229 - New utility class: KeyStrokeManager
  #228 - Turn down scary exception logging in AppProperties

Version 2.6.0 [2025-12-31] - Maintenance release
  #224 - Better extension error handling in ExtensionManager
  #222 - ListSubsetField: support drag and drop
  #220 - ListSubsetField: auto-sorting is optional (default: off)
  #218 - Slight adjustment to HyperlinkUtil.BrowseAction
  #215 - Fix minor bug in SingleInstanceManagerTest
  #213 - New utility method: FileSystemUtil.sanitizeFilename()
  #212 - Absorb HyperlinkUtil from ExtPackager
  #210 - Allow CheckBoxField to get/set checkbox text
  #208 - New FieldValidator: ListEmptySelectionValidator
  #204 - PopupTextDialog: hide Cancel button in read-only mode
  #203 - New FormField: ButtonField / ButtonProperty
  #199 - Cosmetic fix for HtmlLabelField
  #198 - New utility class: TextFileDetector
  #197 - Make Stopwatch utility class thread safe
  #195 - AboutPanel: use HtmlLabelField for swing-extras attribution
  #183 - Absorb SingleInstanceManager class from MusicPlayer
  #180 - Add Property wrappers for panel fields
  #179 - ImageListPanel: fix minor drag-and-drop bug
  #178 - New FormField: HtmlLabelField / HtmlLabelProperty
  #177 - Add "built with swing-extras" option to AboutPanel
  #176 - ExtensionManager: loosen up extension version matching
  #175 - ExtensionManagerDialog: cache downloaded screenshots
  #174 - Improved logging in UpdateManager
  #173 - Fix minor bug when launching LogConsole from AboutDialog
  #112 - New FormField: ListSubsetField / ListSubsetProperty

Version 2.5.0 [2025-12-01] - Dynamic extension discovery
  #171 - UpdateSources: prune local sources automatically
  #170 - UpdateSources: allow variable substitution
  #169 - ImageListPanel wasn't handling isReadOnly properly
  #168 - UpdateManager: more graceful application restarts
  #167 - New UI component: ToggleableTabbedPane
  #166 - Fix Look and Feel bug in ColorField and SliderField
  #165 - Demo app: code cleanup and documentation pass
  #164 - General: callback listeners were not thread safe
  #163 - New FormField: PasswordField
  #161 - MessageUtil: fix warning icon
  #160 - Add a way to compare version strings reliably
  #159 - ImageListPanel: fix minor bug with owner window
  #158 - ExtensionDetailsPanel: make it more flexible
  #157 - ImageListPanel: animated GIF support
  #156 - VersionManifest: use relative paths not URLs
  #155 - General: smarten up listener handling
  #154 - UpdateSource: force manifest and public key to same host
  #153 - ListField: use DefaultListModel as the starting point
  #152 - New FormField: ImageListField
  #151 - UpdateManager: better unit tests
  #150 - UpdateManager: handle downloads asynchronously
  #149 - New dialog: PopupTextDialog
  #148 - MultiProgressDialog: add initial show delay option
  #147 - UpdateManager: add flag to allow SNAPSHOT downloads
  #146 - More customization options in FileField
  #145 - Add FileSystemUtil.extractTextFileFromJar()
  #144 - UpdateManager: Support dynamic application restart
  #143 - ExtensionManagerDialog: rewrite for update support
  #142 - PanelField/CollapsiblePanelField: handle setEnabled()
  #139 - Add FileSystemUtil.getPrintableSize()
  #138 - Add bounds checking to Margins class
  #137 - Improved FormPanel.setBorderMargin() method
  #136 - AbstractProperty: add hook for form field generation
  #135 - CustomizableDesktopPane: add solid color bg option
  #134 - ComboField should expose its underlying model
  #133 - ExtensionManager: change extension resource loading
  #132 - LabelField: make hyperlinks smarter and easier
  #131 - AboutPanel: show if newer version is available
  #130 - ExtensionManager: Better logging on initial load
  #129 - ImageUtil: Faster scanning of image dimensions
  #128 - AboutPanel should warn about snapshot builds
  #127 - Performance improvements in FileSystemUtil
  #126 - Fix resource loading issue in extensions
  #123 - DirTree: fix node comparison bug
  #122 - FormPanel.setEnabled() now works as it should
  #121 - README updates for 2.5.0
  #120 - FormField: setters should be fluent-style
  #119 - Fix flickering during dynamic LongTextField resize
  #116 - Extensions: fix dynamic instantiation issue
  #115 - Fix NullPointerException in Properties
  #114 - FormField: pass on validate if field is invisible
  #113 - FileProperty/DirectoryProperty wired up incorrectly
  #111 - New FormField: CollapsiblePanelField
  #109 - New FormField: SliderField

Version 2.4.0 [2025-09-01] - swing-forms rewrite
  #108 - ExtensionManager: fix config preview bug
  #107 - Fix minor form field alignment bug
  #106 - Allow ESC key to cancel props dialog
  #105 - Add unit tests for all Properties
  #104 - Log and skip UnsupportedOpException in PropsManager
  #103 - Merge ColorField and GradientColorField into one
  #102 - Make AboutPanel smarter about fonts
  #101 - Make FormField's default font customizable
  #100 - Split TextField into short and long fields
  #99 - Deprecate ConfigObject
  #98 - Deprecate ConfigPanel
  #97 - refactor TextField constructors
  #96 - Upgrade Java 11 to Java 17
  #95 - HashUtil: update byteArrayToHexString
  #94 - HashUtil: remove the 2GB file hash size limit
  #93 - HashUtil: log cleanup
  #91 - ComboField should allow custom cell renderers
  #90 - Add custom renderer tab to the demo app
  #89 - Make ListField more flexible and customizable
  #88 - TextField: allow popup editor
  #87 - Change FieldValidator from abstract class to interface
  #86 - Clean up resource handling in swing-forms
  #84 - Rewrite the swing-forms render pipeline
  #83 - Add deprecation warning for ConfigObject and ConfigPanel
  #82 - Refactor FieldValidator
  #80 - Refactor ValidationResult
  #79 - Thorough javadoc pass on swing-forms
  #78 - Refactor FormPanel
  #77 - Refactor FormField
  #76 - Remove ugly hack in FormField
  #75 - Add unit tests for swing-forms
  #74 - ComboProperty and ComboField are now generic
  #73 - Refactor FormField.render()
  #72 - Fix some goofiness in FileField
  #70 - Fix array index out of bounds in ListProperty
  #69 - Fix uncaught exception during extension loading
  #68 - Change the way AbstractProperty exposes form fields

Version 2.3.0 [2025-07-20] - Maintenance release
  #67 - Minor bug in extension config preview
  #66 - Allow subclasses to control PropertiesDialog size
  #65 - FontField.setVisible() was not behaving as expected
  #64 - Add max version check to ExtensionManager
  #62 - Ensure extension config properties are only created once
  #61 - Add static peek() to AppProperties
  #60 - Add ListField and ListProperty for multi-select props
  #59 - Fix cosmetic issue on ExtensionManagerDialog
  #58 - Add extraAttributes to all properties/form fields
  #57 - Add hyperlink option to LabelProperty
  #56 - Add ImageUtil.scaleImageToFitSquareBounds
  #55 - Promote the animation classes from ext-mp-scenery to here
  #54 - Use fluent-style setters for all AbstractProperties
  #52 - Clean up deprecation warning in ExtensionManager
  #49 - Improvements to MultiProgressDialog
  #44 - Allow custom form logic with extension config

Version 2.2.0 [2024-06-10] - ExtensionManager enhancements
  #47 - AppProperties.reinitialize() should also call load()
  #46 - add extension load order to log output
  #43 - PropertiesDialog should have a way to force subcat labels
  #42 - hide release notes on extension manager dialog
  #41 - add a way to control extension load order
  #39 - Allow extensions to share config properties
  #33 - view extension config in ExtensionManagerDialog
  #32 - show source dir and jar file on extension manager dialog

Version 2.1.0 [2025-05-17] - LookAndFeel support
  #38 - image icon loading/scaling convenience in ImageUtil
  #37 - more image loading convenience methods in ImageUtil
  #36 - make extInfo loading easier for extensions
  #35 - Fix high CPU usage in ImagePanel.paintComponent
  #34 - Fix ExtensionManager dependency load issues
  #31 - Add a way to listen for LaF changes
  #30 - LookAndFeelProperty not storing correctly
  #29 - Make label top/bottom margins configurable
  #28 - Support JTattoo LaF options
  #27 - ImagePanel should support LaF
  #26 - Odd JList behaviour when switching LaF
  #24 - Support FlatLaf Laf options
  #23 - ExtensionManagerDialog ignoring LaF
  #22 - NullPointerException in AppProperties.load()
  #21 - LookAndFeel support

Version 2.0.0 [2025-04-13]
  - New unified demo app
  - Moved documentation to swing-extras-book and greatly expanded
  #9 - Absorbed app-extensions library into swing-extras
  #15 - Absorbed swing-forms library into swing-extras

Version 1.9.4 [2025-04-10]
  - Bug: FileField.setEnabled wasn't working
  - Bug: ComboBox's item listener was wrong
  - PanelField now responds to validation
  #19 - Fix cosmetic glitch in progress bars
  #17 - New help tooltip support in all form fields
  #16 - New FontField and FontProperty
  #14 - Fix high CPU usage in PlaybackThread

Version 1.9.3 [2025-04-05]
  #12 - Fix ClassCastException introduced in 1.9.2

Version 1.9.2 [2025-04-04]
  #10 - PlaybackThread needs better reporting
  #8 - LabelProperty should ignore saveToProps
  #7 - Properties should allow read-only initial state
  #6 - PropertiesDialog: add scrollbars to long forms
  #5 - PropertiesManager.generateDialog can return null
  #4 - PropertiesManager: allow custom form logic pre-render

Version 1.9.1 [2025-03-26]
  #2 - Add EnumProperty for easier management of enum properties
  #1 - Change ConfigObject from abstract class to interface

Version 1.9 [2025-03-09]
  - Project moved to GitHub

Version 1.8 [2024-12-30] - ExtensionManager/PropertiesManager/EMS
  [UTIL-141] - NumberField(String, SpinnerModel) should be public
  [UTIL-142] - Escape should close AboutDialog
  [UTIL-143] - Import image text writing from CapRoulette
  [UTIL-144] - ImagePanel should expose translatePoint()
  [UTIL-145] - Add ExtensionManager class
  [UTIL-146] - Add PropertiesManager class
  [UTIL-147] - FormPanel.render() can be invoked again
  [UTIL-148] - Add ExtensionDialog
  [UTIL-149] - EMS handlers should have usage info
  [UTIL-150] - EMS Command registry should list commands
  [UTIL-151] - EMS: clients need an identifier
  [UTIL-152] - EMS: merge CommandRegistry into EMSServer
  [UTIL-153] - Add demo panel for EMS
  [UTIL-154] - EMSClient
  [UTIL-155] - EMS: add EMSServerSpy
  [UTIL-156] - Add EMSClientListener
  [UTIL-157] - EMS is not handling threading very well
  [UTIL-158] - Forms: TextField needs a scroll pane
  [UTIL-159] - ExtensionManager: add way to manually add extensions
  [UTIL-160] - Add demo panel for ExtensionManager
  [UTIL-161] - Forms: FileField should support nullable directories
  [UTIL-162] - DirTree should handle nulls better
  [UTIL-163] - TextField needs more size options
  [UTIL-164] - ExtensionManager: add extension type
  [UTIL-165] - Forms: let me set field margins individually
  [UTIL-166] - PropertiesDialog - let me specify a left margin
  [UTIL-167] - AppExtensionInfo: use builder pattern
  [UTIL-168] - Add json serialization wrapper
  [UTIL-169] - AppExtensionInfo needs custom fields
  [UTIL-170] - Extensions should package an extInfo.json
  [UTIL-171] - ExtensionManager should be less abstract
  [UTIL-172] - build script should make a fat jar
  [UTIL-173] - Adjust spacing of header fields in PropertiesManager
  [UTIL-174] - Need a way to change form field label
  [UTIL-175] - Stopwatch shows 0s for very low values
  [UTIL-176] - Stopwatch needs a public format method
  [UTIL-177] - Small typos in ExtensionDetailsPanel
  [UTIL-178] - IntegerProperty and DecimalProperty simple options
  [UTIL-179] - Don't package apache commons io
  [UTIL-181] - Minor: ok/cancel buttons on prefs dialog are small

Version 1.7 [2023-03-17] - DesktopPane, LogConsole, animated GIFs
  [UTIL-117] - AboutPanel not scrolling to top of release notes
  [UTIL-119] - Bug: FileBasedProperties doesn't save on remove
  [UTIL-120] - Bug: FileBasedProperties isn't saving correctly
  [UTIL-121] - make FileSystemUtil.findFiles methods easier
  [UTIL-122] - Absorb CustomDesktopPane from Snotes
  [UTIL-123] - Bug: ColorField adding mouse listener in wrong place
  [UTIL-124] - YMDDate needs a getDayName()
  [UTIL-125] - Project changes for 1.7 release
  [UTIL-126] - Add LogConsole
  [UTIL-127] - LogConsole should have a way to persist theme choice
  [UTIL-128] - LogConsole should have a way to customize output
  [UTIL-129] - Add a Stopwatch utility for timing tracking
  [UTIL-130] - Add LogConsole demo tab
  [UTIL-131] - LogConsole should return quickly if not visible
  [UTIL-132] - LogConsole: theme switch resets font size
  [UTIL-133] - LogConsole should expose themes
  [UTIL-134] - Bug: CheckBoxField should not use ChangeListener
  [UTIL-135] - FileBasedProperties should expose its File
  [UTIL-136] - YMDDate should have more flexible constructors
  [UTIL-137] - ImagePanel should support animated GIFs
  [UTIL-138] - ImageUtil should support animated GIFs
  [UTIL-139] - Bug: LabelField setting hyperlink on wrong label
  [UTIL-140] - Properties.getColor() is wrong

Version 1.6 [2022-05-10] - Properties, progress, gradients, and more
  [UTIL-92] - AboutPanel should allow showing custom fields
  [UTIL-93] - Switch to Properties instead of Preferences
  [UTIL-94] - Project updates for 1.6 release
  [UTIL-95] - Bug: ImageWriter has changed in newer Java version
  [UTIL-96] - Better use of logging throughout
  [UTIL-97] - Make better use of unit testing
  [UTIL-98] - Create FileBasedProperties
  [UTIL-99] - AudioUtil needs a way to limit size of waveform images
  [UTIL-100] - Add progress handling utilities
  [UTIL-101] - MessageUtil should allow warnings
  [UTIL-102] - AboutPanel custom fields should be updateable
  [UTIL-103] - More intelligent color property loading
  [UTIL-104] - Performance: fix FileSystemUtil.findSubdirectories
  [UTIL-105] - FileBasedProperties should order the list of props
  [UTIL-106] - Make ImagePanel extensible
  [UTIL-107] - LogoConfig and Generator needs cleanup
  [UTIL-108] - Add Gradient generation support
  [UTIL-109] - Add "swap colors" button to GradientConfigDialog
  [UTIL-110] - Add ColorChooser
  [UTIL-111] - Implement gradient support for text and line drawing
  [UTIL-112] - LogoConfigPanel should use standard change listeners
  [UTIL-113] - Forms: FontField is wonky
  [UTIL-114] - NumberField has a hard-coded component size
  [UTIL-115] - ImageUtil.generateThumbnail is wonky
  [UTIL-116] - Update release notes for 1.6 release

Version 1.5 [2022-04-11] - Maintenance release
  [UTIL-42] - WaveformConfig save and/or load is wrong
  [UTIL-72] - Consider providing a SqlDAO abstract class
  [UTIL-73] - Project updates for 1.5 release
  [UTIL-74] - FileField.getFile() has problems with blank input
  [UTIL-75] - JdbcSqlDAO.delete() has an invalid condition
  [UTIL-76] - Expose jpeg compression quality in ImageUtil
  [UTIL-77] - Remove FormBuilder factory class
  [UTIL-78] - ImageUtil.deserializeImage can't handle null input
  [UTIL-79] - AboutPanel should show app dir and home dir
  [UTIL-80] - FormField.setFieldLabelFont() is broken
  [UTIL-81] - Absorb the new ProgressDialog from Darwin into sc-util
  [UTIL-82] - Add an installer script
  [UTIL-83] - Add package-info.java to all directories
  [UTIL-84] - Bug: YMDDate is in the wrong package
  [UTIL-85] - Pretty up the AboutPanel a lot
  [UTIL-86] - Create MessageUtil
  [UTIL-87] - MultiProgressDialog: grey out cancel when clicked
  [UTIL-88] - Consider absorbing SplashWindow from Darwin
  [UTIL-89] - LogoGenerator needs cleanup
  [UTIL-90] - Add ImagePanelConfig convenience getter
  [UTIL-91] - AboutPanel and Dialog need a way to refresh mem stats

Version 1.4 [2020-10-07] - Maintenance release
  [UTIL-26] - Add a FormBuilder component
  [UTIL-43] - YMDDate needs a .equals implementation
  [UTIL-44] - Minor: release notes should auto-scroll to top
  [UTIL-45] - ModelObject.delete() is triggering a recreate
  [UTIL-46] - ModelObject needs a LoadMode
  [UTIL-47] - Splash screen may have gone missing
  [UTIL-48] - Update version properties for 1.4 release
  [UTIL-49] - DAO class needs a configurable ModelObject cache
  [UTIL-50] - ModelObject needs a way to listen for modifications
  [UTIL-51] - YMDDate.setDate() should be smarter about blanks
  [UTIL-52] - FormFields shouldn't validate themselves when disabled
  [UTIL-53] - LabelFields are still showing their validation label
  [UTIL-54] - AboutPanel should show sc-util version
  [UTIL-55] - Add a FontField form field for choosing a Font
  [UTIL-56] - Add a Numeric/spinner FormField
  [UTIL-57] - FormPanel should have leftAlign and topAlign options
  [UTIL-58] - Margin issues in LabelField and TextField
  [UTIL-59] - ComboField needs a way to update after field creation
  [UTIL-60] - Form validation tooltip shows empty tip when valid
  [UTIL-61] - showValidationLabel should be smarter
  [UTIL-62] - YMDDateValidator should have an allowBlank option
  [UTIL-63] - Add a PanelField to FormBuilder
  [UTIL-64] - Need a way to clear fields from a FormPanel
  [UTIL-65] - Move rendering code to FormPanel; allow re-rendering
  [UTIL-66] - TextFields aren't line wrapping
  [UTIL-67] - Need a way to directly access label for a component
  [UTIL-68] - LabelField needs to expose "extra" margin properties
  [UTIL-69] - ModelObject.firePropertyChangedEvent is broken
  [UTIL-70] - TextField should be expandable if multi-line
  [UTIL-71] - FormField.addFieldValidator should reject duplicates

Version 1.3 [2019-11-07] - Maintenance release
  [UTIL-36] - YMDDate needs a copy constructor
  [UTIL-37] - Add AboutDialog and AboutPanel as generic components
  [UTIL-38] - Add ModelObject and DAO base classes
  [UTIL-39] - Upgrade to Netbeans/Java 11
  [UTIL-40] - Absorb LogoGenerator into sc-util
  [UTIL-41] - Need a LogoConfigPanel

Version 1.2 [2018-02-04] - Maintenance release
  [UTIL-33] - Remove debug statements in audio util
  [UTIL-34] - Refactoring: clean up naming of config objects
  [UTIL-35] - NegativeArraySizeException in some cases

Version 1.1 [2018-01-28] - Maintenance release
  [UTIL-19] - Add AudioUtil
  [UTIL-20] - ImagePanel: refactor display mode
  [UTIL-21] - HashUtil: add additional digest options
  [UTIL-22] - Create a demo/testing application
  [UTIL-23] - ImagePanel: STRETCH mode fails after refresh
  [UTIL-24] - Add stream support to AudioUtil
  [UTIL-25] - Add AudioWaveformPanel
  [UTIL-27] - Cut/copy/paste support in AudioWaveformPanel
  [UTIL-28] - Create a YMDDate wrapper class
  [UTIL-29] - WaveformPreferences: allow saving/loading via Prefs
  [UTIL-30] - Add a generic ConfigPanel base class
  [UTIL-31] - Add WaveformPreferencesConfigPanel
  [UTIL-32] - Add ImagePanelPreferencesConfigPanel

Version 1.0 [2018-01-02] - Initial version
  [UTIL-1] - Migrate ImageUtil from ICE to util project
  [UTIL-2] - Migrate HashUtil from ICE project
  [UTIL-3] - Migrate FileSystemUtil from ICE project
  [UTIL-4] - Create project skeleton and build.xml file
  [UTIL-5] - Create Jenkins build and deploy job
  [UTIL-6] - Unit tests: HashUtil
  [UTIL-7] - Migrate ImagePanel from ICE project
  [UTIL-8] - ImagePanel: make it more configurable
  [UTIL-9] - ImagePanel: allow disabling the use magnifier cursor
  [UTIL-10] - Migrate DirTree from ImageView project
  [UTIL-11] - Import WrapUtil from ICE
  [UTIL-12] - ImagePanel is stealing mouse wheel events
  [UTIL-13] - ImagePanel: add a map of configurable properties
  [UTIL-14] - DirTree is sorting directory names stupidly
  [UTIL-15] - ImagePanel not resizing the image properly
  [UTIL-16] - DirTree needs a "reload"
  [UTIL-17] - ImagePanel auto best fit is wonky sometimes
  [UTIL-18] - FileSystemUtil default sort file is wrong
