/* UIDefaults.java -- database for all settings and interface bindings.
   Copyright (C) 2002, 2004, 2005  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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;

/**
 * UIDefaults is a database where all settings and interface bindings are
 * stored into. A PLAF implementation fills one of these (see for example
 * plaf/basic/BasicLookAndFeel.java) with "ButtonUI" -&gt; new BasicButtonUI().
 *
 * @author Ronald Veldema (rveldema@cs.vu.nl)
 */
public class UIDefaults extends Hashtable
{
  private LinkedList bundles;
  private Locale defaultLocale;
  private PropertyChangeSupport propertyChangeSupport;

  public static interface ActiveValue
  {
    Object createValue(UIDefaults table);
  }

  public static class LazyInputMap implements LazyValue
  {
    Object[] bind;
    public LazyInputMap(Object[] bindings)
    {
      bind = bindings;
    }
    public Object createValue(UIDefaults table)
    {
      InputMap im = new InputMap ();
      for (int i = 0; 2*i+1 < bind.length; ++i)
        {
          im.put (KeyStroke.getKeyStroke ((String) bind[2*i]),
                  bind[2*i+1]);
        }
      return im;
    }
  }

  public static interface LazyValue
  {
    Object createValue(UIDefaults table);
  }

  public static class ProxyLazyValue implements LazyValue
  {
    LazyValue inner;
    public ProxyLazyValue(String s)
    {
      final String className = s;
      inner = new LazyValue ()
        { 
          public Object createValue (UIDefaults table) 
          {
            try
              {
                return Class
                  .forName(className)
                  .getConstructor(new Class[] {})
                  .newInstance(new Object[] {});
              }
            catch (Exception e)
              {
                return null;
              }
          }
        };
    }

    public ProxyLazyValue(String c, String m)
    {
      final String className = c;
      final String methodName = m;
      inner = new LazyValue ()
        { 
          public Object createValue (UIDefaults table) 
          {
            try 
              {                
                return Class
                  .forName (className)
                  .getMethod (methodName, new Class[] {})
                  .invoke (null, new Object[] {});
              }
            catch (Exception e)
              {
                return null;
              }
          }
        };
    }
    
    public ProxyLazyValue(String c, Object[] os)
    {
      final String className = c;
      final Object[] objs = os;
      final Class[] clss = new Class[objs.length];
      for (int i = 0; i < objs.length; ++i)
        {
          clss[i] = objs[i].getClass();
        }      
      inner = new LazyValue()
        { 
          public Object createValue(UIDefaults table) 
          {            
            try
              {
                return Class
                  .forName(className)
                  .getConstructor(clss)
                  .newInstance(objs);
	      }
            catch (Exception e)
	      {
                return null;
              }
          }
        };
    }

    public ProxyLazyValue(String c, String m, Object[] os)
    {
      final String className = c;
      final String methodName = m;
      final Object[] objs = os;
      final Class[] clss = new Class[objs.length];
      for (int i = 0; i < objs.length; ++i)
	{
          clss[i] = objs[i].getClass();
	}
      inner = new LazyValue()
        { 
	  public Object createValue(UIDefaults table)
	  {
            try 
              {
                return Class
                  .forName(className)
                  .getMethod(methodName, clss)
                  .invoke(null, objs);
              }
            catch (Exception e)
              {
                return null;
              }
          }
        };
    }
    
    public Object createValue(UIDefaults table)
    {
      return inner.createValue(table);
    }
  }

  private static final long serialVersionUID = 7341222528856548117L;

  public UIDefaults()
  {
    bundles = new LinkedList();
    defaultLocale = Locale.getDefault();
    propertyChangeSupport = new PropertyChangeSupport(this);
  }

  public UIDefaults(Object[] entries)
  {
    this();
    
    for (int i = 0; (2 * i + 1) < entries.length; ++i)
      put(entries[2 * i], entries[2 * i + 1]);
  }

  public Object get(Object key)
  {
    return this.get(key, getDefaultLocale());
  }

  public Object get(Object key, Locale loc)
  {
    Object obj = null;

    if (super.containsKey(key))
      {
        obj = super.get(key);
      }
    else if (key instanceof String)
      {
        String keyString = (String) key;
        ListIterator i = bundles.listIterator(0);
        while (i.hasNext())
	  {
            String bundle_name = (String) i.next();
            ResourceBundle res =
              ResourceBundle.getBundle(bundle_name, loc);
            if (res != null)
              {
                try 
                  {                    
                    obj = res.getObject(keyString);
                    break;
                  }
                catch (MissingResourceException me)
                  {
                    // continue, this bundle has no such key
                  }
              }
          }
      }

    // now we've found the object, resolve it.
    // nb: LazyValues aren't supported in resource bundles, so it's correct
    // to insert their results in the locale-less hashtable.

    if (obj == null)
      return null;

    if (obj instanceof LazyValue)
      {
        Object resolved = ((LazyValue) obj).createValue(this);
        super.remove(key);
        super.put(key, resolved);
        return resolved;
      }
    else if (obj instanceof ActiveValue)
      {
        return ((ActiveValue) obj).createValue(this);
      }    

    return obj;
  }

  public Object put(Object key, Object value)
  {
    Object old;
    if (value != null)
      old = super.put(key, value);
    else
      old = super.remove(key);
    if (key instanceof String && old != value)
      firePropertyChange((String) key, old, value);
    return old;
  }

  public void putDefaults(Object[] entries)
  {
    for (int i = 0; (2 * i + 1) < entries.length; ++i)
  {
        super.put(entries[2 * i], entries[2 * i + 1]);
      }
    firePropertyChange("UIDefaults", null, null);
  }

  public Font getFont(Object key)
  {
    Object o = get(key);
    return o instanceof Font ? (Font) o : null;
  }

  public Font getFont(Object key, Locale l)
  {
    Object o = get(key, l);
    return o instanceof Font ? (Font) o : null;
  }

  public Color getColor(Object key)
  {
    Object o = get(key);
    return o instanceof Color ? (Color) o : null;
  }

  public Color getColor(Object key, Locale l)
  {
    Object o = get(key, l);
    return o instanceof Color ? (Color) o : null;
  }

  public Icon getIcon(Object key)
  {
    Object o = get(key);
    return o instanceof Icon ? (Icon) o : null;
  }

  public Icon getIcon(Object key, Locale l)
  {
    Object o = get(key, l);
    return o instanceof Icon ? (Icon) o : null;
  }

  public Border getBorder(Object key)
  {
    Object o = get(key);
    return o instanceof Border ? (Border) o : null;
  }

  public Border getBorder(Object key, Locale l)
  {
    Object o = get(key, l);
    return o instanceof Border ? (Border) o : null;
  }

  public String getString(Object key)
  {
    Object o = get(key);
    return o instanceof String ? (String) o : null;
  }

  public String getString(Object key, Locale l)
  {
    Object o = get(key, l);
    return o instanceof String ? (String) o : null;
  }

  public int getInt(Object key)
  {
    Object o = get(key);
    return o instanceof Integer ? ((Integer) o).intValue() : 0;
  }

  public int getInt(Object key, Locale l)
  {
    Object o = get(key, l);
    return o instanceof Integer ? ((Integer) o).intValue() : 0;
  }

  public boolean getBoolean(Object key)
  {
    return Boolean.TRUE.equals(get(key));
  }

  public boolean getBoolean(Object key, Locale l)
  {
    return Boolean.TRUE.equals(get(key, l));
  }

  public Insets getInsets(Object key) 
  {
    Object o = get(key);
    return o instanceof Insets ? (Insets) o : null;
  }

  public Insets getInsets(Object key, Locale l) 
  {
    Object o = get(key, l);
    return o instanceof Insets ? (Insets) o : null;
  }

  public Dimension getDimension(Object key) 
  {
    Object o = get(key);
    return o instanceof Dimension ? (Dimension) o : null;
  }

  public Dimension getDimension(Object key, Locale l) 
  {
    Object o = get(key, l);
    return o instanceof Dimension ? (Dimension) o : null;
  }

  public Class getUIClass(String id, ClassLoader loader)
  {
    String className = (String) get (id);
    if (className == null)
      return null;
    try 
      {
        if (loader != null)
          return loader.loadClass (className);    
        return Class.forName (className);
      }
    catch (Exception e)
      {
        return null;
      }
  }

  public Class getUIClass(String id)
  {
    return getUIClass (id, null);
  }

  protected void getUIError(String msg)
  {
    System.err.println ("UIDefaults.getUIError: " + msg);
  }

  public ComponentUI getUI(JComponent target)
  {
    String classId = target.getUIClassID ();
    Class cls = getUIClass (classId);
    if (cls == null)
      {
        getUIError ("failed to locate UI class:" + classId);
        return null;
      }

    Method factory;

    try 
      {
        factory = cls.getMethod ("createUI", new Class[] { JComponent.class } );
      }
    catch (NoSuchMethodException nme)
      {
        getUIError ("failed to locate createUI method on " + cls.toString ());
        return null;
      }

    try
      {
        return (ComponentUI) factory.invoke (null, new Object[] { target });
      }
    catch (java.lang.reflect.InvocationTargetException ite)
      {
        getUIError ("InvocationTargetException ("+ ite.getTargetException() 
		    +") calling createUI(...) on " + cls.toString ());
        return null;        
      }
    catch (Exception e)
      {
        getUIError ("exception calling createUI(...) on " + cls.toString ());
        return null;        
      }
  }

  public void addPropertyChangeListener(PropertyChangeListener listener)
  {
    propertyChangeSupport.addPropertyChangeListener(listener);
  }

  public void removePropertyChangeListener(PropertyChangeListener listener)
  {
    propertyChangeSupport.removePropertyChangeListener(listener);
  }

  public PropertyChangeListener[] getPropertyChangeListeners()
  {
    return propertyChangeSupport.getPropertyChangeListeners();
  }

  protected void firePropertyChange(String property,
				    Object oldValue, Object newValue)
  {
    propertyChangeSupport.firePropertyChange(property, oldValue, newValue);
  }

  public void addResourceBundle(String name)
  {
    bundles.addFirst(name);
  }

  public void removeResourceBundle(String name)
  {
    bundles.remove(name);
  }

  public void setDefaultLocale(Locale loc)
  {
    defaultLocale = loc;
  }

  public Locale getDefaultLocale()
  {
    return defaultLocale;
  }
}
