/*
    VLDocking Framework 2.1
    Copyright VLSOLUTIONS, 2004-2006

    email : info@vlsolutions.com
------------------------------------------------------------------------
This software is distributed under the CeCILL license, a GNU GPL-compatible
license adapted to french law.
French and English license headers are provided at the begining of
the source files of this software application.
------------------------------------------------------------------------
LICENCE CeCILL (FRENCH VERSION).
------------------------------------------------------------------------
Ce logiciel est un programme informatique servant à améliorer les interfaces
homme-machine d'applications Java basées sur Swing, en leur apportant un
ensemble de fonctions relatives au dockage des composants.

Ce logiciel est régi par la licence CeCILL soumise au droit français et
respectant les principes de diffusion des logiciels libres. Vous pouvez
utiliser, modifier et/ou redistribuer ce programme sous les conditions
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
sur le site "http://www.cecill.info".

En contrepartie de l'accessibilité au code source et des droits de copie,
de modification et de redistribution accordés par cette licence, il n'est
offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,
seule une responsabilité restreinte pèse sur l'auteur du programme,  le
titulaire des droits patrimoniaux et les concédants successifs.

A cet égard  l'attention de l'utilisateur est attirée sur les risques
associés au chargement,  à l'utilisation,  à la modification et/ou au
développement et à la reproduction du logiciel par l'utilisateur étant
donné sa spécificité de logiciel libre, qui peut le rendre complexe à
manipuler et qui le réserve donc à des développeurs et des professionnels
avertis possédant  des  connaissances  informatiques approfondies.  Les
utilisateurs sont donc invités à charger  et  tester  l'adéquation  du
logiciel à leurs besoins dans des conditions permettant d'assurer la
sécurité de leurs systèmes et ou de leurs données et, plus généralement,
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.

Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
pris connaissance de la licence CeCILL, et que vous en avez accepté les
termes.

------------------------------------------------------------------------
CeCILL License (ENGLISH VERSION)
------------------------------------------------------------------------

This software is a computer program whose purpose is to enhance Human-Computer
Interfaces written in Java with the Swing framework, providing them a set of
functions related to component docking.

This software is governed by the CeCILL  license under French law and
abiding by the rules of distribution of free software.  You can  use,
modify and/ or redistribute the software under the terms of the CeCILL
license as circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info".

As a counterpart to the access to the source code and  rights to copy,
modify and redistribute granted by the license, users are provided only
with a limited warranty  and the software's author,  the holder of the
economic rights,  and the successive licensors  have only  limited
liability.

In this respect, the user's attention is drawn to the risks associated
with loading,  using,  modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean  that it is complicated to manipulate,  and  that  also
therefore means  that it is reserved for developers  and  experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or
data to be ensured and,  more generally, to use and operate it in the
same conditions as regards security.

The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms.

*/


package com.vlsolutions.swing.toolbars;

import java.awt.BorderLayout;
import java.awt.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import java.awt.FlowLayout;



/** The container for toolbar panels.
 *<p>
 * The layout used is BorderLayout and the CENTER component is dedicated to the user
 * (the other 4 places (NORTH, EAST, WEST and SOUTH are used to display the toolbar panels)).
 *
 * <p align="center"><img src="doc-files/overview.gif"><br>
 *  The ToolBarContainer is a JPanel with a BorderLayout, containing a user component and a maximum of four
 * ToolBarPanels.
 * </p>
 *
 *<p>
 * Loading and saving toolbar configurations is done with the {@link ToolBarIO} utility class, and works if
 * VLToolbars are registered (given a name and made know to their container by {@link #registerToolBar(VLToolBar)} ).
 *
 * @author Lilian Chamontin, VLSolutions
 * @update 2006/09/09 Support for LTR/RTL orientation
 */
public class ToolBarContainer extends JPanel {
  
  private Map componentsByContraints = new HashMap(); // this is private in borderlayout, so we need to keep a copy here
  private Map contraintsByComponents = new HashMap();
  
  private Map toolBarsByName = new HashMap();
  
  public ToolBarContainer() {
    setLayout(new BorderLayout());
  }
  
  /** Registers a new ToolBar.
   *<p>
   * Registering is used when reading a xml configuration
   */
  public void registerToolBar(VLToolBar toolbar){
    if (toolbar.getName() == null){
      throw new IllegalArgumentException("This toolbar hasn't got a name : cannot be registered");
    }
    toolBarsByName.put(toolbar.getName(), toolbar);
  }
  
  /** Unregisters a ToolBar.
   *<p>
   * Registering is used when reading a xml configuration
   */
  public void unregisterToolBar(VLToolBar toolbar){
    if (toolbar.getName() == null){
      return;
    }
    toolBarsByName.remove(toolbar.getName());
  }
  
  /** Returns the registered toolbar associated with the given name, or null if not found
   */
  public VLToolBar getToolBarByName(String name){
    return (VLToolBar)toolBarsByName.get(name);
  }
  
  /** Returns the list of currently registered toolbars.
   *
   *<p> (eturns a new list at each invocation.)
   */
  public List getRegisteredToolBars() {
    return new ArrayList(toolBarsByName.values());
  }
  
  /** Overriden to track component constraints  */
  public void add(Component comp, Object constraints){
    super.add(comp, constraints);
    componentsByContraints.put(constraints, comp);
    contraintsByComponents.put(comp, constraints);
    if (comp instanceof ToolBarPanel){
      ToolBarPanel panel = (ToolBarPanel) comp;
      if (constraints.equals(BorderLayout.EAST) || constraints.equals(BorderLayout.WEST)){
        panel.setOrientation(SwingConstants.VERTICAL);
      }
      // install the UI border
      if (constraints.equals(BorderLayout.NORTH)){
        panel.setBorder(UIManager.getBorder("ToolBarPanel.topBorder"));
      } else if (constraints.equals(BorderLayout.WEST)){
        panel.setBorder(UIManager.getBorder("ToolBarPanel.leftBorder"));
      } else if (constraints.equals(BorderLayout.EAST)){
        panel.setBorder(UIManager.getBorder("ToolBarPanel.rightBorder"));
      } else if (constraints.equals(BorderLayout.SOUTH)){
        panel.setBorder(UIManager.getBorder("ToolBarPanel.bottomBorder"));
      }
    }
  }
  
  /** Overriden to keep track of component constraints  */
  public void remove(Component comp){
    super.remove(comp);
    Object constraints = contraintsByComponents.remove(comp);
    componentsByContraints.remove(constraints);
  }
  
  /** Overriden to keep track of component constraints  */
  public void remove(int index){
    Component comp = getComponent(index);
    super.remove(index);
    Object constraints = contraintsByComponents.remove(comp);
    componentsByContraints.remove(constraints);
  }
  /** Overriden to keep track of component constraints  */
  public void removeAll(){
    super.removeAll();
    componentsByContraints.clear();
    contraintsByComponents.clear();
  }
  
  /** Returns the component for a given BorderLayout constraints */
  public Component getComponentAt(Object constraints){
    return (Component)componentsByContraints.get(constraints);
  }
  
  /** Returns the ToolBarPanel for a given BorderLayout constraints  */
  public ToolBarPanel getToolBarPanelAt(Object constraints){
    return (ToolBarPanel) getComponentAt(constraints);
  }
  
  /** Returns the BorderLayout constraints of the given component */
  public Object getConstraints(Component comp){
    return contraintsByComponents.get(comp);
  }
  
  /** Creates a default ToolBarContainer with preinstalled toolbar panels on the borders with
   * the LEADING alignment.
   *<p>
   * The toolbarPanels are then accessible with getToolBarPanelAt(constraints) where constraints values
   * are BorderLayout.NORTH, EAST, WEST and SOUTH.
   */
  public static ToolBarContainer createDefaultContainer(boolean topToolbar, boolean leftToolBar,
      boolean bottomToolBar, boolean rightToolBar){
    return createDefaultContainer(topToolbar, leftToolBar, bottomToolBar, rightToolBar,
        FlowLayout.LEADING);
  }
  
  /** Creates a default ToolBarContainer with preinstalled toolbar panels on the borders with
   * the specified alignment
   * The value of the alignment argument must be one of
   * <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
   * <code>FlowLayout.CENTER</code>, <code>FlowLayout.LEADING</code>, or
   * <code>FlowLayout.TRAILING</code>.
   *<p>
   * The toolbarPanels are then accessible with getToolBarPanelAt(constraints) where constraints values
   * are BorderLayout.NORTH, EAST, WEST and SOUTH.
   *
   *@author KDMurthy, Marathon Project.
   */
  public static ToolBarContainer createDefaultContainer(boolean topToolbar, boolean leftToolBar,
      boolean bottomToolBar, boolean rightToolBar, int alignment){
    
    
    ToolBarContainer container = new ToolBarContainer();
    if (topToolbar){
      ToolBarPanel panel = new ToolBarPanel(alignment);
      panel.setVisible(false);
      container.add(panel, BorderLayout.NORTH);
    }
    if (leftToolBar){
      ToolBarPanel panel = new ToolBarPanel(alignment);
      panel.setVisible(false);
      container.add(panel, BorderLayout.WEST);
    }
    if (bottomToolBar){
      ToolBarPanel panel = new ToolBarPanel(alignment);
      panel.setVisible(false);
      container.add(panel, BorderLayout.SOUTH);
    }
    if (rightToolBar){
      ToolBarPanel panel = new ToolBarPanel(alignment);
      panel.setVisible(false);
      container.add(panel, BorderLayout.EAST);
    }
    return container;
    
  }
  
}
