CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-codehaus-groovy--groovy-swing

A declarative Swing GUI builder for Groovy applications that provides a concise and maintainable way to create complex Swing user interfaces

Pending
Overview
Eval results
Files

look-and-feel.mddocs/

Look and Feel Management

Simplified Look and Feel management with support for system LAFs and third-party themes, providing easy access to platform-specific appearance and custom styling.

Capabilities

LookAndFeelHelper

The central helper class for managing Look and Feel configuration with built-in support for popular LAFs.

/**
 * Singleton helper for Look and Feel management
 */
class LookAndFeelHelper {
    /** Get singleton instance */
    static LookAndFeelHelper getInstance()
    
    /** Configure Look and Feel with attributes and initialization code */
    LookAndFeel lookAndFeel(Object value, Map attributes = [:], Closure initClosure = null)
    
    /** Register alias for Look and Feel class name */
    String addLookAndFeelAlias(String alias, String className)
    
    /** Add custom attribute handler for specific LAF */
    String addLookAndFeelAttributeHandler(String className, String attr, Closure handler)
    
    /** Check if this is a leaf node in builder pattern */
    boolean isLeaf()
}

Built-in Look and Feel Aliases

Pre-configured aliases for common Look and Feel implementations.

// System Look and Feels
'system'        // UIManager.getSystemLookAndFeelClassName()
'crossPlatform' // UIManager.getCrossPlatformLookAndFeelClassName()

// Platform-specific LAFs
'metal'   // javax.swing.plaf.metal.MetalLookAndFeel
'nimbus'  // com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel (if available)
'windows' // com.sun.java.swing.plaf.windows.WindowsLookAndFeel
'win2k'   // com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel
'mac'     // com.apple.laf.AquaLookAndFeel (if available)
'motif'   // com.sun.java.swing.plaf.motif.MotifLookAndFeel
'gtk'     // com.sun.java.swing.plaf.gtk.GTKLookAndFeel
'synth'   // javax.swing.plaf.synth.SynthLookAndFeel

// Third-party LAFs (requires external libraries)
'plastic'   // com.jgoodies.looks.plastic.PlasticLookAndFeel
'plastic3D' // com.jgoodies.looks.plastic.Plastic3DLookAndFeel
'plasticXP' // com.jgoodies.looks.plastic.PlasticXPLookAndFeel
'substance' // org.pushingpixels.substance.api.SubstanceLookAndFeel
'napkin'    // net.sourceforge.napkinlaf.NapkinLookAndFeel

Usage Examples:

import groovy.swing.SwingBuilder

// Set system Look and Feel
SwingBuilder.lookAndFeel('system')

// Try multiple LAFs in fallback order
SwingBuilder.lookAndFeel('nimbus', 'system', 'metal')

// Set LAF with configuration
SwingBuilder.lookAndFeel('metal', [
    theme: 'ocean',
    boldFonts: false
])

// Use LAF with initialization closure
SwingBuilder.lookAndFeel('nimbus') { laf ->
    // Custom initialization code
    UIManager.put('control', new Color(240, 240, 240))
}

SwingBuilder LAF Integration

Look and Feel methods integrated into SwingBuilder for convenient usage.

/**
 * SwingBuilder static methods for LAF management
 */
class SwingBuilder {
    /** Configure LAF with single parameter */
    static LookAndFeel lookAndFeel(Object laf)
    
    /** Configure LAF with initialization closure */
    static LookAndFeel lookAndFeel(Object laf, Closure initCode)
    
    /** Configure LAF with attributes and optional closure */
    static LookAndFeel lookAndFeel(Map attributes = [:], Object laf = null, Closure initCode = null)
    
    /** Try multiple LAFs in order until one succeeds */
    static LookAndFeel lookAndFeel(Object... lafs)
}

Usage Examples:

// Simple LAF setting
SwingBuilder.lookAndFeel('nimbus')

// LAF with initialization
SwingBuilder.lookAndFeel('metal') { laf ->
    MetalLookAndFeel.setCurrentTheme(new OceanTheme())
}

// LAF with attributes
SwingBuilder.lookAndFeel([theme: 'steel'], 'metal')

// Fallback LAF selection
SwingBuilder.lookAndFeel('substance', 'nimbus', 'system')

Metal Look and Feel Customization

Special support for Metal LAF themes and configuration.

// Metal LAF extended attributes
[
    theme: 'ocean' | 'steel' | MetalTheme,  // Predefined or custom theme
    boldFonts: boolean,                      // Enable/disable bold fonts
    noxp: boolean                           // Disable XP styling
]

Usage Examples:

// Ocean theme with bold fonts disabled
SwingBuilder.lookAndFeel('metal', [
    theme: 'ocean',
    boldFonts: false
])

// Steel theme (classic Metal)
SwingBuilder.lookAndFeel('metal', [theme: 'steel'])

// Custom Metal theme
import javax.swing.plaf.metal.*

class CustomMetalTheme extends DefaultMetalTheme {
    String getName() { 'Custom Theme' }
    ColorUIResource getPrimary1() { new ColorUIResource(66, 33, 66) }
}

SwingBuilder.lookAndFeel('metal', [theme: new CustomMetalTheme()])

Substance Look and Feel Integration

Support for Substance LAF skins and themes (requires external library).

// Substance LAF extended attributes  
[
    theme: Object,      // Substance theme object
    skin: Object,       // Substance skin object
    watermark: Object   // Substance watermark object
]

Usage Examples:

// Substance with skin (requires Substance library)
try {
    SwingBuilder.lookAndFeel('substance', [
        skin: 'org.pushingpixels.substance.api.skin.BusinessSkin'
    ])
} catch (Exception e) {
    // Fallback to system LAF
    SwingBuilder.lookAndFeel('system')
}

Custom Look and Feel Registration

Methods for registering custom LAF aliases and attribute handlers.

/**
 * Register custom LAF alias
 */
String addLookAndFeelAlias(String alias, String className)

/**
 * Add custom attribute handler for specific LAF
 */
String addLookAndFeelAttributeHandler(String className, String attr, Closure handler)

Usage Examples:

def helper = LookAndFeelHelper.getInstance()

// Register custom LAF alias
helper.addLookAndFeelAlias('myLaf', 'com.example.MyLookAndFeel')

// Add custom attribute handler
helper.addLookAndFeelAttributeHandler(
    'com.example.MyLookAndFeel',
    'customProperty'
) { laf, value ->
    laf.setCustomProperty(value)
}

// Use custom LAF
SwingBuilder.lookAndFeel('myLaf', [customProperty: 'value'])

LAF Utilities and Helpers

Utility methods for LAF detection and management.

/**
 * Static utility methods for LAF detection
 */
class LookAndFeelHelper {
    /** Get Nimbus LAF class name if available */
    static String getNimbusLAFName()
    
    /** Get Aqua LAF class name if available (Mac) */
    static String getAquaLAFName()
    
    /** Get Substance LAF class name if available */
    static String getSubstanceLAFName()
}

// UIManager utilities
UIManager.getSystemLookAndFeelClassName()
UIManager.getCrossPlatformLookAndFeelClassName()
UIManager.getInstalledLookAndFeels()
UIManager.getLookAndFeel()

Usage Examples:

// Check available LAFs
def installedLafs = UIManager.getInstalledLookAndFeels()
println "Available LAFs:"
installedLafs.each { lafInfo ->
    println "  ${lafInfo.name}: ${lafInfo.className}"
}

// Conditional LAF selection based on platform
def platformLaf = System.getProperty('os.name').toLowerCase().contains('mac') ? 'mac' : 'system'
SwingBuilder.lookAndFeel(platformLaf)

// Get current LAF information
def currentLaf = UIManager.getLookAndFeel()
println "Current LAF: ${currentLaf.name} (${currentLaf.class.name})"

Application Integration

Best practices for integrating LAF management into applications.

// Application startup LAF configuration
class Application {
    static void initializeLookAndFeel() {
        // Set LAF before creating any Swing components
        SwingBuilder.lookAndFeel('nimbus', 'system')
        
        // Configure global UI properties
        UIManager.put('OptionPane.messageFont', new Font('Dialog', Font.PLAIN, 12))
        UIManager.put('OptionPane.buttonFont', new Font('Dialog', Font.PLAIN, 12))
    }
    
    static void main(String[] args) {
        SwingUtilities.invokeLater {
            initializeLookAndFeel()
            createAndShowGUI()
        }
    }
}

Usage Examples:

// Complete application LAF setup
import groovy.swing.SwingBuilder
import javax.swing.*

class MyApplication {
    static void main(String[] args) {
        // Initialize LAF early
        SwingUtilities.invokeLater {
            // Try preferred LAFs with fallback
            SwingBuilder.lookAndFeel('nimbus', 'system', 'metal')
            
            // Create main GUI
            def swing = new SwingBuilder()
            def frame = swing.frame(
                title: 'My Application',
                defaultCloseOperation: JFrame.EXIT_ON_CLOSE,
                size: [800, 600]
            ) {
                menuBar {
                    menu(text: 'View') {
                        menu(text: 'Look and Feel') {
                            UIManager.installedLookAndFeels.each { lafInfo ->
                                menuItem(text: lafInfo.name) {
                                    actionPerformed { e ->
                                        try {
                                            UIManager.setLookAndFeel(lafInfo.className)
                                            SwingUtilities.updateComponentTreeUI(frame)
                                        } catch (Exception ex) {
                                            JOptionPane.showMessageDialog(frame, 
                                                "Failed to set LAF: ${ex.message}")
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                panel {
                    // main content
                }
            }
            frame.visible = true
        }
    }
}

Error Handling

Proper error handling for LAF operations.

// LAF setting with error handling
try {
    SwingBuilder.lookAndFeel('preferredLaf')
} catch (UnsupportedLookAndFeelException e) {
    println "LAF not supported: ${e.message}"
    SwingBuilder.lookAndFeel('system') // fallback
} catch (ClassNotFoundException e) {
    println "LAF class not found: ${e.message}"
    SwingBuilder.lookAndFeel('metal') // fallback
} catch (Exception e) {
    println "LAF error: ${e.message}"
    // Keep current LAF
}

Usage Examples:

// Robust LAF selection with logging
def selectLookAndFeel() {
    def candidates = ['nimbus', 'system', 'metal']
    
    for (laf in candidates) {
        try {
            SwingBuilder.lookAndFeel(laf)
            println "Successfully set LAF: $laf"
            return
        } catch (Exception e) {
            println "Failed to set LAF $laf: ${e.message}"
        }
    }
    
    println "Warning: Using default LAF"
}

// Dynamic LAF switching in running application
def switchLookAndFeel(String lafName, Component rootComponent) {
    try {
        def oldLaf = UIManager.getLookAndFeel()
        SwingBuilder.lookAndFeel(lafName)
        SwingUtilities.updateComponentTreeUI(rootComponent)
        println "Switched from ${oldLaf.name} to ${UIManager.getLookAndFeel().name}"
    } catch (Exception e) {
        JOptionPane.showMessageDialog(rootComponent, 
            "Could not switch to $lafName: ${e.message}",
            'Look and Feel Error', 
            JOptionPane.ERROR_MESSAGE)
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-codehaus-groovy--groovy-swing

docs

data-binding.md

extensions.md

gui-building.md

index.md

layout-management.md

look-and-feel.md

models.md

tile.json