/* MultiSplitPaneUI.java --
   Copyright (C) 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., 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.plaf.multi;

import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Iterator;
import java.util.Vector;

import javax.accessibility.Accessible;
import javax.swing.JComponent;
import javax.swing.JSplitPane;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.SplitPaneUI;

/**
 * A UI delegate that that coordinates multiple {@link SplitPaneUI}
 * instances, one from the primary look and feel, and one or more from the
 * auxiliary look and feel(s).
 *
 * @see UIManager#addAuxiliaryLookAndFeel(LookAndFeel)
 */
public class MultiSplitPaneUI extends SplitPaneUI
{

  /** A list of references to the actual component UIs. */
  protected Vector uis;

  /**
   * Creates a new <code>MultiSplitPaneUI</code> instance.
   *
   * @see #createUI(JComponent)
   */
  public MultiSplitPaneUI()
  {
    uis = new Vector();
  }

  /**
   * Creates a delegate object for the specified component.  If any auxiliary
   * look and feels support this component, a <code>MultiSplitPaneUI</code> is
   * returned, otherwise the UI from the default look and feel is returned.
   *
   * @param target  the component.
   *
   * @see MultiLookAndFeel#createUIs(ComponentUI, Vector, JComponent)
   */
  public static ComponentUI createUI(JComponent target)
  {
    MultiSplitPaneUI mui = new MultiSplitPaneUI();
    return MultiLookAndFeel.createUIs(mui, mui.uis, target);
  }

  /**
   * Calls the {@link ComponentUI#installUI(JComponent)} method for all
   * the UI delegates managed by this <code>MultiSplitPaneUI</code>.
   *
   * @param c  the component.
   */
  public void installUI(JComponent c)
  {
    Iterator iterator = uis.iterator();
    while (iterator.hasNext())
    {
      ComponentUI ui = (ComponentUI) iterator.next();
      ui.installUI(c);
    }
  }

  /**
   * Calls the {@link ComponentUI#uninstallUI(JComponent)} method for all
   * the UI delegates managed by this <code>MultiSplitPaneUI</code>.
   *
   * @param c  the component.
   */
  public void uninstallUI(JComponent c)
  {
    Iterator iterator = uis.iterator();
    while (iterator.hasNext())
    {
      ComponentUI ui = (ComponentUI) iterator.next();
      ui.uninstallUI(c);
    }
  }

  /**
   * Returns an array containing the UI delegates managed by this
   * <code>MultiSplitPaneUI</code>.  The first item in the array is always
   * the UI delegate from the installed default look and feel.
   *
   * @return An array of UI delegates.
   */
  public ComponentUI[] getUIs()
  {
    return MultiLookAndFeel.uisToArray(uis);
  }

  /**
   * Calls the {@link ComponentUI#contains(JComponent, int, int)} method for all
   * the UI delegates managed by this <code>MultiSplitPaneUI</code>,
   * returning the result for the UI delegate from the primary look and
   * feel.
   *
   * @param c  the component.
   * @param x  the x-coordinate.
   * @param y  the y-coordinate.
   *
   * @return <code>true</code> if the specified (x, y) coordinate falls within
   *         the bounds of the component as rendered by the UI delegate in the
   *         primary look and feel, and <code>false</code> otherwise.
   */
  public boolean contains(JComponent c, int x, int y)
  {
    boolean result = false;
    Iterator iterator = uis.iterator();
    // first UI delegate provides the return value
    if (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        result = ui.contains(c, x, y);
      }
    // return values from auxiliary UI delegates are ignored
    while (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        /* boolean ignored = */ ui.contains(c, x, y);
      }
    return result;
  }

  /**
   * Calls the {@link ComponentUI#update(Graphics, JComponent)} method for all
   * the UI delegates managed by this <code>MultiSplitPaneUI</code>.
   *
   * @param g  the graphics device.
   * @param c  the component.
   */
  public void update(Graphics g, JComponent c)
  {
    Iterator iterator = uis.iterator();
    while (iterator.hasNext())
    {
      ComponentUI ui = (ComponentUI) iterator.next();
      ui.update(g, c);
    }
  }

  /**
   * Calls the <code>paint(Graphics, JComponent)</code> method for all the UI
   * delegates managed by this <code>MultiSplitPaneUI</code>.
   *
   * @param g  the graphics device.
   * @param c  the component.
   */
  public void paint(Graphics g, JComponent c)
  {
    Iterator iterator = uis.iterator();
    while (iterator.hasNext())
    {
      ComponentUI ui = (ComponentUI) iterator.next();
      ui.paint(g, c);
    }
  }

  /**
   * Calls the {@link ComponentUI#getPreferredSize(JComponent)} method for all
   * the UI delegates managed by this <code>MultiSplitPaneUI</code>,
   * returning the preferred size for the UI delegate from the primary look and
   * feel.
   *
   * @param c  the component.
   *
   * @return The preferred size returned by the UI delegate from the primary
   *         look and feel.
   */
  public Dimension getPreferredSize(JComponent c)
  {
    Dimension result = null;
    Iterator iterator = uis.iterator();
    // first UI delegate provides the return value
    if (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        result = ui.getPreferredSize(c);
      }
    // return values from auxiliary UI delegates are ignored
    while (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        /* Dimension ignored = */ ui.getPreferredSize(c);
      }
    return result;
  }

  /**
   * Calls the {@link ComponentUI#getMinimumSize(JComponent)} method for all
   * the UI delegates managed by this <code>MultiSplitPaneUI</code>,
   * returning the minimum size for the UI delegate from the primary look and
   * feel.
   *
   * @param c  the component.
   *
   * @return The minimum size returned by the UI delegate from the primary
   *         look and feel.
   */
  public Dimension getMinimumSize(JComponent c)
  {
    Dimension result = null;
    Iterator iterator = uis.iterator();
    // first UI delegate provides the return value
    if (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        result = ui.getMinimumSize(c);
      }
    // return values from auxiliary UI delegates are ignored
    while (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        /* Dimension ignored = */ ui.getMinimumSize(c);
      }
    return result;
  }

  /**
   * Calls the {@link ComponentUI#getMaximumSize(JComponent)} method for all
   * the UI delegates managed by this <code>MultiSplitPaneUI</code>,
   * returning the maximum size for the UI delegate from the primary look and
   * feel.
   *
   * @param c  the component.
   *
   * @return The maximum size returned by the UI delegate from the primary
   *         look and feel.
   */
  public Dimension getMaximumSize(JComponent c)
  {
    Dimension result = null;
    Iterator iterator = uis.iterator();
    // first UI delegate provides the return value
    if (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        result = ui.getMaximumSize(c);
      }
    // return values from auxiliary UI delegates are ignored
    while (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        /* Dimension ignored = */ ui.getMaximumSize(c);
      }
    return result;
  }

  /**
   * Calls the {@link ComponentUI#getAccessibleChildrenCount(JComponent)} method
   * for all the UI delegates managed by this <code>MultiSplitPaneUI</code>,
   * returning the count for the UI delegate from the primary look and
   * feel.
   *
   * @param c  the component.
   *
   * @return The count returned by the UI delegate from the primary
   *         look and feel.
   */
  public int getAccessibleChildrenCount(JComponent c)
  {
    int result = 0;
    Iterator iterator = uis.iterator();
    // first UI delegate provides the return value
    if (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        result = ui.getAccessibleChildrenCount(c);
      }
    // return values from auxiliary UI delegates are ignored
    while (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        /* int ignored = */ ui.getAccessibleChildrenCount(c);
      }
    return result;
  }

  /**
   * Calls the {@link ComponentUI#getAccessibleChild(JComponent, int)} method
   * for all the UI delegates managed by this <code>MultiSplitPaneUI</code>,
   * returning the child for the UI delegate from the primary look and
   * feel.
   *
   * @param c  the component
   * @param i  the child index.
   *
   * @return The child returned by the UI delegate from the primary
   *         look and feel.
   */
  public Accessible getAccessibleChild(JComponent c, int i)
  {
    Accessible result = null;
    Iterator iterator = uis.iterator();
    // first UI delegate provides the return value
    if (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        result = ui.getAccessibleChild(c, i);
      }
    // return values from auxiliary UI delegates are ignored
    while (iterator.hasNext())
      {
        ComponentUI ui = (ComponentUI) iterator.next();
        /* Accessible ignored = */ ui.getAccessibleChild(c, i);
      }
    return result;
  }

  /**
   * Calls the {@link SplitPaneUI#resetToPreferredSizes(JSplitPane)} method
   * for all the UI delegates managed by this <code>MultiSplitPaneUI</code>.
   *
   * @param pane  the component.
   */
  public void resetToPreferredSizes(JSplitPane pane)
  {
    Iterator iterator = uis.iterator();
    while (iterator.hasNext())
    {
      SplitPaneUI ui = (SplitPaneUI) iterator.next();
      ui.resetToPreferredSizes(pane);
    }
  }

  /**
   * Calls the {@link SplitPaneUI#setDividerLocation(JSplitPane, int)} method
   * for all the UI delegates managed by this <code>MultiSplitPaneUI</code>.
   *
   * @param pane  the component.
   * @param location  the location.
   */
  public void setDividerLocation(JSplitPane pane, int location)
  {
    Iterator iterator = uis.iterator();
    while (iterator.hasNext())
    {
      SplitPaneUI ui = (SplitPaneUI) iterator.next();
      ui.setDividerLocation(pane, location);
    }
  }

  /**
   * Calls the {@link SplitPaneUI#getDividerLocation(JSplitPane)} method for all
   * the UI delegates managed by this <code>MultiSplitPaneUI</code>,
   * returning the location for the UI delegate from the primary look and
   * feel.
   *
   * @param pane  the component.
   *
   * @return The location returned by the UI delegate from the primary
   *         look and feel.
   */
  public int getDividerLocation(JSplitPane pane)
  {
    int result = 0;
    Iterator iterator = uis.iterator();
    // first UI delegate provides the return value
    if (iterator.hasNext())
      {
        SplitPaneUI ui = (SplitPaneUI) iterator.next();
        result = ui.getDividerLocation(pane);
      }
    // return values from auxiliary UI delegates are ignored
    while (iterator.hasNext())
      {
        SplitPaneUI ui = (SplitPaneUI) iterator.next();
        /* int ignored = */ ui.getDividerLocation(pane);
      }
    return result;
  }

  /**
   * Calls the {@link SplitPaneUI#getMinimumDividerLocation(JSplitPane)} method
   * for all the UI delegates managed by this <code>MultiSplitPaneUI</code>,
   * returning the location for the UI delegate from the primary look and
   * feel.
   *
   * @param pane  the component.
   *
   * @return The location returned by the UI delegate from the primary
   *         look and feel.
   */
  public int getMinimumDividerLocation(JSplitPane pane)
  {
    int result = 0;
    Iterator iterator = uis.iterator();
    // first UI delegate provides the return value
    if (iterator.hasNext())
      {
        SplitPaneUI ui = (SplitPaneUI) iterator.next();
        result = ui.getMinimumDividerLocation(pane);
      }
    // return values from auxiliary UI delegates are ignored
    while (iterator.hasNext())
      {
        SplitPaneUI ui = (SplitPaneUI) iterator.next();
        /* int ignored = */ ui.getMinimumDividerLocation(pane);
      }
    return result;
  }

  /**
   * Calls the {@link SplitPaneUI#getMaximumDividerLocation(JSplitPane)} method
   * for all the UI delegates managed by this <code>MultiSplitPaneUI</code>,
   * returning the location for the UI delegate from the primary look and
   * feel.
   *
   * @param pane  the component.
   *
   * @return The location returned by the UI delegate from the primary
   *         look and feel.
   */
  public int getMaximumDividerLocation(JSplitPane pane)
  {
    int result = 0;
    Iterator iterator = uis.iterator();
    // first UI delegate provides the return value
    if (iterator.hasNext())
      {
        SplitPaneUI ui = (SplitPaneUI) iterator.next();
        result = ui.getMaximumDividerLocation(pane);
      }
    // return values from auxiliary UI delegates are ignored
    while (iterator.hasNext())
      {
        SplitPaneUI ui = (SplitPaneUI) iterator.next();
        /* int ignored = */ ui.getMaximumDividerLocation(pane);
      }
    return result;
  }

  /**
   * Calls the {@link SplitPaneUI#finishedPaintingChildren(JSplitPane,
   * Graphics)} method for all the UI delegates managed by this
   * <code>MultiSplitPaneUI</code>.
   *
   * @param pane  the component.
   * @param g  the graphics device.
   */
  public void finishedPaintingChildren(JSplitPane pane, Graphics g)
  {
    Iterator iterator = uis.iterator();
    while (iterator.hasNext())
    {
      SplitPaneUI ui = (SplitPaneUI) iterator.next();
      ui.finishedPaintingChildren(pane, g);
    }
  }

}
