/* LookAndFeel.java --
   Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Toolkit;
import java.net.URL;

import javax.swing.border.Border;
import javax.swing.plaf.ComponentInputMapUIResource;
import javax.swing.plaf.IconUIResource;
import javax.swing.plaf.InputMapUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.text.JTextComponent;

/**
 * A <i>look-and-feel</i> controls most aspects of the appearance and 
 * operation of user interface components in <code>javax.swing</code>.  A 
 * cross-platform look-and-feel (the {@link MetalLookAndFeel}) is provided.
 * 
 * @see UIManager#getInstalledLookAndFeels()
 * @see UIManager#setLookAndFeel(LookAndFeel)
 */
public abstract class LookAndFeel
{
  /**
   * Creates and returns a look-and-feel specific defaults table.  This method 
   * is called once by {@link UIManager#setLookAndFeel(LookAndFeel)} and 
   * shouldn't be called again (as it creates a large table of defaults).
   *
   * @return The UI defaults.
   */
  public UIDefaults getDefaults()
  {
    return null;
  }

  /**
   * Returns a description of the look and feel.
   * 
   * @return A description of the look and feel.
   */
  public abstract String getDescription();

  /**
   * Returns the value of <code>Toolkit.getDefaultToolkit()
   * .getDesktopProperty(systemPropertyName)</code>, or 
   * <code>fallbackValue</code> if no such property is defined.
   * 
   * @param systemPropertyName  the system property name.
   * @param fallbackValue  the fallback value.
   * 
   * @return The property value or <code>fallbackValue</code>.
   */
  public static Object getDesktopPropertyValue(String systemPropertyName, 
      Object fallbackValue)
  {
    Object value = Toolkit.getDefaultToolkit().getDesktopProperty(
        systemPropertyName);
    return value != null ? value : fallbackValue;
  }
  
  /**
   * Returns an identifier for the look and feel.
   * 
   * @return An identifier for the look and feel.
   */
  public abstract String getID();

  /**
   * Returns the name for the look and feel.
   * 
   * @return The name for the look and feel.
   */
  public abstract String getName();

  /**
   * Returns <code>true</code> when the look-and-feel supports window 
   * decorations, and <code>false</code> otherwise. This default implementation
   * always returns <code>false</code> and needs to be overridden when the 
   * derived look-and-feel supports this.
   *
   * @return <code>false</code>.
   *
   * @since 1.4
   */
  public boolean getSupportsWindowDecorations()
  {
    return false;
  }
  
  /**
   * Initializes the look-and-feel.  The 
   * {@link UIManager#setLookAndFeel(LookAndFeel)} method calls this method 
   * before the first call (and typically the only call) to 
   * {@link #getDefaults()}.  This default implementation does nothing, but
   * subclasses can override this behaviour. 
   */
  public void initialize()
  {
    // We do nothing here. This method is meant to be overridden by
    // LookAndFeel implementations.
  }

  /**
   * Convenience method for installing a component's default {@link Border} 
   * object on the specified component if either the border is currently 
   * <code>null</code> or already an instance of {@link UIResource}. 
   * 
   * @param c  the component (<code>null</code> not permitted).
   * @param defaultBorderName  the border name (for lookup in the UIDefaults 
   *     table).
   */
  public static void installBorder(JComponent c, String defaultBorderName)
  {
    Border b = c.getBorder();
    if (b == null || b instanceof UIResource)
      c.setBorder(UIManager.getBorder(defaultBorderName));
  }

  /**
   * Convenience method for initializing a component's foreground and
   * background color properties with values from the current defaults table.
   * 
   * @param c  the component (<code>null</code> not permitted).
   * @param defaultBgName  the key for the background color in the UIDefaults 
   *     table.
   * @param defaultFgName  the key for the foreground color in the UIDefaults
   *     table.
   */
  public static void installColors(JComponent c, String defaultBgName,
                                   String defaultFgName)
  {
    // Install background.
    Color bg = c.getBackground();
    if (bg == null || bg instanceof UIResource)
      c.setBackground(UIManager.getColor(defaultBgName));

    // Install foreground.
    Color fg = c.getForeground();
    if (fg == null || fg instanceof UIResource)
      c.setForeground(UIManager.getColor(defaultFgName));
  }

  /**
   * Convenience method for initializing a component's foreground, background
   * and font properties with values from the current defaults table.
   * 
   * @param component  the component (<code>null</code> not permitted).
   * @param defaultBgName  the key for the background color in the UIDefaults 
   *     table.
   * @param defaultFgName  the key for the foreground color in the UIDefaults
   *     table.
   * @param defaultFontName  the key for the font in the UIDefaults table.
   */
  public static void installColorsAndFont(JComponent component,
                                          String defaultBgName,
                                          String defaultFgName,
                                          String defaultFontName)
  {
    // Install colors.
    installColors(component, defaultBgName, defaultFgName);
    // Install font.
    Font f = component.getFont();
    if (f == null || f instanceof UIResource)
      component.setFont(UIManager.getFont(defaultFontName));
  }

  /**
   * Returns <code>true</code> if the look-and-feel is the "native" 
   * look-and-feel for the current platform, and <code>false</code> otherwise.
   * A native look-and-feel emulates the appearance and behaviour of the 
   * default windowing system on the host operating system.
   * 
   * @return A flag indicating whether or not this is the native look and feel
   *         for the current platform.
   */
  public abstract boolean isNativeLookAndFeel();

  /**
   * Returns <code>true</code> if the look-and-feel is supported on the 
   * current operating system, and <code>false</code> otherwise.  This 
   * mechanism is provided so that it is possible to prevent a look-and-feel
   * from being used on some operating systems (usually for legal, not
   * technical, reasons).
   * 
   * @return A flag indicating whether or not the look-and-feel is supported
   *         on the current platform.
   */
  public abstract boolean isSupportedLookAndFeel();

  /**
   * Loads the bindings in keys into retMap. Does not remove existing entries
   * from retMap.  <code>keys</code> describes the InputMap, every even indexed
   * item is either a KeyStroke or a String representing a KeyStroke and every
   * odd indexed item is the Object associated with that KeyStroke in an 
   * ActionMap.
   * 
   * @param retMap the InputMap into which we load bindings
   * @param keys the Object array describing the InputMap as above
   */
  public static void loadKeyBindings(InputMap retMap, Object[] keys)
  {
    if (keys == null)
      return;
    for (int i = 0; i < keys.length - 1; i += 2)
      {
        Object key = keys[i];
        KeyStroke keyStroke;
        if (key instanceof KeyStroke)
          keyStroke = (KeyStroke) key;
        else
          keyStroke = KeyStroke.getKeyStroke((String) key);
        retMap.put(keyStroke, keys[i + 1]);
      }
  }

  /**
   * Creates a ComponentInputMap from keys.  
   * <code>keys</code> describes the InputMap, every even indexed
   * item is either a KeyStroke or a String representing a KeyStroke and every
   * odd indexed item is the Object associated with that KeyStroke in an 
   * ActionMap.
   * 
   * @param c the JComponent associated with the ComponentInputMap
   * @param keys the Object array describing the InputMap as above
   * 
   * @return A new input map.
   */
  public static ComponentInputMap makeComponentInputMap(JComponent c,
							Object[] keys)
  {
    ComponentInputMap retMap = new ComponentInputMapUIResource(c);
    loadKeyBindings(retMap, keys);
    return retMap;
  }

  /**
   * Utility method that creates a UIDefaults.LazyValue that creates an
   * ImageIcon UIResource for the specified gifFile filename.
   * 
   * @param baseClass  the base class for accessing the icon resource.
   * @param gifFile  the file name.
   * 
   * @return A {@link UIDefaults.LazyValue} that serves up an 
   *     {@link IconUIResource}.
   */
  public static Object makeIcon(Class baseClass, String gifFile)
  {
    final URL file = baseClass.getResource(gifFile);
    return new UIDefaults.LazyValue() 
      {
        public Object createValue(UIDefaults table)
        {
          return new IconUIResource(new ImageIcon(file));
        }
      };
  }

  /**
   * Creates a InputMap from keys. 
   * <code>keys</code> describes the InputMap, every even indexed
   * item is either a KeyStroke or a String representing a KeyStroke and every
   * odd indexed item is the Object associated with that KeyStroke in an 
   * ActionMap.
   * 
   * @param keys the Object array describing the InputMap as above
   * 
   * @return A new input map.
   */
  public static InputMap makeInputMap(Object[] keys)
  {
    InputMap retMap = new InputMapUIResource();
    loadKeyBindings(retMap, keys);
    return retMap;
  }

  /**
   * Convenience method for building lists of KeyBindings.
   * <code>keyBindingList</code> is an array of KeyStroke-Action pairs where
   * even indexed elements are KeyStrokes or Strings representing KeyStrokes
   * and odd indexed elements are the associated Actions.
   * 
   * @param keyBindingList the array of KeyStroke-Action pairs
   * @return a JTextComponent.KeyBinding array
   */
  public static JTextComponent.KeyBinding[] makeKeyBindings(
      Object[] keyBindingList)
  {
    JTextComponent.KeyBinding[] retBindings = 
      new JTextComponent.KeyBinding[keyBindingList.length / 2];
    for (int i = 0; i < keyBindingList.length - 1; i += 2)
      {
        KeyStroke stroke;
        if (keyBindingList[i] instanceof KeyStroke)
          stroke = (KeyStroke) keyBindingList[i];
        else
          stroke = KeyStroke.getKeyStroke((String) keyBindingList[i]);
        retBindings[i / 2] = new JTextComponent.KeyBinding(stroke, 
            (String) keyBindingList[i + 1]);
      }
    return retBindings;
  }

  /**
   * Invoked when the user attempts an invalid operation. The default 
   * implementation just beeps. Subclasses that wish to change this need to 
   * override this method.
   *
   * @param component the component the error occured in
   */
  public void provideErrorFeedback(Component component)
  {
    Toolkit.getDefaultToolkit().beep();
  }

  /**
   * Returns a string that displays and identifies this object's properties.
   *
   * @return string containing the description and class name.
   */
  public String toString()
  {
    return getDescription() + " " + getClass().getName();
  }

  /**
   * UIManager.setLookAndFeel calls this method just before we're replaced by
   * a new default look and feel. 
   */
  public void uninitialize()
  {
    // We do nothing here. This method is meant to be overridden by
    // LookAndFeel implementations.
  }

  /**
   * Convenience method for un-installing a component's default border on the
   * specified component if the border is currently an instance of UIResource.
   * 
   * @param c  the component (<code>null</code> not permitted).
   */
  public static void uninstallBorder(JComponent c)
  {
    if (c.getBorder() instanceof UIResource)
      c.setBorder(null);
  }

  /**
   * This methods installs a UI property if it hasn't already been set by an
   * application. This method is used by UI delegates that install a default
   * value for a property with a primitive type but do not want to override
   * a value that has been set by an application.
   *
   * The supported properties depend on the actual type of the component and
   * are listed in the table below. The supported properties are of course
   * inherited to subclasses.
   *
   * <table>
   * <tr><th>Type</th><th>Supported properties</th></tr>
   * <tr><td><code>JComponent</code></td>
   *     <td><code>opaque, autoscrolls</code></td></tr>
   * <tr><td><code>AbstractButton</code></td>
   *     <td><code>borderPainted, rolloverEnabled, iconTextGap,
   *      contentAreaFilled</code></td></tr>
   * <tr><td><code>JDesktopPane</code></td>
   *     <td><code>dragMode</code></td></tr>
   * <tr><td><code>JSplitPane</code></td>
   *     <td><code>dividerSize, oneTouchExpandable</code></td></tr>
   * <tr><td><code>JTable</code></td>
   *     <td><code>rowHeight</code></td></tr>
   * <tr><td><code>JTree</code></td>
   *     <td><code>rowHeight, scrollsOnExpand, showsRootHandles</code></td></tr>
   * </table>
   *
   * @param c the component to install the property to
   * @param propertyName the name of the property
   * @param value the value of the property
   *
   * @throws IllegalArgumentException if the specified property cannot be set
   *         by this method
   * @throws ClassCastException if the property value does not match the
   *         property type
   * @throws NullPointerException if <code>c</code> or
   *         <code>propertyValue</code> is <code>null</code>
   *
   * @since 1.5
   */
  public static void installProperty(JComponent c, String propertyName,
                                     Object value)
  {
    c.setUIProperty(propertyName, value);
  }
}
