001/* 002 * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * o Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * o Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * o Neither the name of JGoodies Karsten Lentzsch nor the names of 015 * its contributors may be used to endorse or promote products derived 016 * from this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 020 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 021 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 027 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030 031package com.jgoodies.forms.util; 032 033import java.beans.PropertyChangeEvent; 034import java.beans.PropertyChangeListener; 035 036import javax.swing.LookAndFeel; 037import javax.swing.UIManager; 038 039/** 040 * Consists only of static utility methods. 041 * 042 * This class may be merged with the FormLayoutUtils extra - or not. * 043 * 044 * @author Karsten Lentzsch 045 * @version $Revision$ 046 */ 047public final class Utilities { 048 049 // Instance ************************************************************* 050 051 private Utilities() { 052 // Suppresses default constructor, ensuring non-instantiability. 053 } 054 055 /** 056 * Lazily checks and answers whether the Aqua look&feel is active. 057 * 058 * @return true if the current look&feel is Aqua 059 */ 060 public static boolean isLafAqua() { 061 if (cachedIsLafAqua == null) { 062 cachedIsLafAqua = Boolean.valueOf(computeIsLafAqua()); 063 ensureLookAndFeelChangeHandlerRegistered(); 064 } 065 return cachedIsLafAqua.booleanValue(); 066 } 067 068 // Caching and Lazily Computing the Laf State ***************************** 069 070 /** 071 * Holds the cached result of the Aqua l&f check. 072 * Is invalidated by the <code>LookAndFeelChangeHandler</code> 073 * if the look&feel changes. 074 */ 075 private static Boolean cachedIsLafAqua; 076 077 /** 078 * Describes whether the <code>LookAndFeelChangeHandler</code> 079 * has been registered with the <code>UIManager</code> or not. 080 * It is registered lazily when the first cached l&f state is computed. 081 */ 082 private static boolean lafChangeHandlerRegistered = false; 083 084 private static synchronized void ensureLookAndFeelChangeHandlerRegistered() { 085 if (!lafChangeHandlerRegistered) { 086 UIManager.addPropertyChangeListener(new LookAndFeelChangeHandler()); 087 lafChangeHandlerRegistered = true; 088 } 089 } 090 091 /** 092 * Computes and answers whether the Aqua look&feel is active. 093 * 094 * @return true if the current look&feel is Aqua 095 */ 096 private static boolean computeIsLafAqua() { 097 LookAndFeel laf = UIManager.getLookAndFeel(); 098 return laf.getName().startsWith("Mac OS X Aqua"); 099 } 100 101 /** 102 * Listens to changes of the Look and Feel and invalidates the cache. 103 */ 104 private static final class LookAndFeelChangeHandler 105 implements PropertyChangeListener { 106 107 /** 108 * Invalidates the cached laf states, if the UIManager has fired 109 * any property change event. Since we need to handle look&feel 110 * changes only, we check the event's property name to be 111 * "lookAndFeel" or <code>null</code>. The check for null is necessary 112 * to handle the special event where property name, old and new value 113 * are all <code>null</code> to indicate that multiple properties 114 * have changed. 115 * 116 * @param evt describes the property change 117 */ 118 @Override 119 public void propertyChange(PropertyChangeEvent evt) { 120 String propertyName = evt.getPropertyName(); 121 if (propertyName == null || propertyName.equals("lookAndFeel")) { 122 cachedIsLafAqua = null; 123 } 124 } 125 } 126 127}