001    /*
002     * This file is part of the Echo Point Project.  This project is a
003     * collection of Components that have extended the Echo Web Application
004     * Framework Version 3.
005     *
006     * Version: MPL 1.1
007     *
008     * The contents of this file are subject to the Mozilla Public License Version
009     * 1.1 (the "License"); you may not use this file except in compliance with
010     * the License. You may obtain a copy of the License at
011     * http://www.mozilla.org/MPL/
012     *
013     * Software distributed under the License is distributed on an "AS IS" basis,
014     * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
015     * for the specific language governing rights and limitations under the
016     * License.
017     */
018    
019    package echopoint;
020    
021    import echopoint.internal.AbstractContainer;
022    import nextapp.echo.app.Component;
023    import nextapp.echo.app.IllegalChildException;
024    
025    import java.util.LinkedHashMap;
026    import java.util.List;
027    import java.util.Map;
028    
029    /**
030     * An implementation of {@link java.awt.BorderLayout} using a HTML table with
031     * three rows, and three columns.  Note that similar to pane containers, this
032     * component supports only one child component per region.
033     *
034     * <p>The following shows sample use of this container component.</p>
035     * <pre>
036     *  import echopoint.BorderLayout;
037     *  import echopoint.HtmlLabel;
038     *  import nextapp.echo.app.Alignment;
039     *  import nextapp.echo.app.Color;
040     *  import nextapp.echo.app.Extent;
041     *  import nextapp.echo.app.layout.TableLayoutData;
042     *
043     *    ...
044     *    final BorderLayout container = new BorderLayout();
045     *    container.setWidth( new Extent( 500 ) );
046     *
047     *    HtmlLabel label = new HtmlLabel( "North" );
048     *    TableLayoutData layout = new TableLayoutData();
049     *    layout.setAlignment( Alignment.ALIGN_CENTER );
050     *    layout.setBackground( new Color( 0x0000ff ) );
051     *    label.setLayoutData( layout );
052     *    container.add( label, BorderLayout.Region.north );
053     *
054     *    ...
055     *
056     *    parent.add( container );
057     * </pre>
058     *
059     * @author Rakesh 2009-04-02
060     * @version $Id: BorderLayout.java 146 2009-04-07 16:00:41Z sptrakesh $
061     * @since 3.0.0a11
062     */
063    public class BorderLayout extends AbstractContainer
064    {
065      private static final long serialVersionUID = 1L;
066    
067      /** Enumeration for the regions in a border layout. */
068      public enum Region
069      {
070        /** The region that represents the north (top) area of the layout container. */
071        north,
072    
073        /** The region that represents the west (left) area of the layout container. */
074        west,
075    
076        /** The region that represents the centre (default) area of the layout container. */
077        center,
078    
079        /** The region that represents the east (right) area of the layout container. */
080        east,
081    
082        /** The region that represents the south (bottom) area of the layout container. */
083        south
084      }
085    
086      /** A map used to maintain the regions to the component indices. */
087      private Map<Region,Integer> regionToIndex = new LinkedHashMap<Region,Integer>( 5 );
088    
089      /** A map used to maintain the mapping of component index to region. */
090      private Map<Integer,Region> indexToRegion = new LinkedHashMap<Integer,Region>( 5 );
091    
092      /** Default constructor.  No special actions required. */
093      public BorderLayout() {}
094    
095      /**
096       * Create a new instance using the specified list of child components in
097       * order {@link Region#north}, {@link Region#west}, {@link Region#center},
098       * {@link Region#east}, and {@link Region#south}.  If the specified list has
099       * only one child, it is added to the {@link Region#center} area.
100       *
101       * @param list The list of child components.
102       * @throws IllegalArgumentException If the list contains more than 5 components.
103       */
104      public BorderLayout( final List<Component> list )
105      {
106        if ( list.size() > 5 )
107        {
108          throw new IllegalArgumentException(
109              "BorderLayout can contain only 5 child components" );
110        }
111    
112        if ( list.size() == 1 )
113        {
114          add( list.get( 0 ) );
115        }
116        else
117        {
118          for ( int i = 0; i < list.size(); ++i )
119          {
120            Region region;
121    
122            switch ( i )
123            {
124              case 0:
125                region = Region.north;
126                break;
127              case 1:
128                region = Region.west;
129                break;
130              case 3:
131                region = Region.east;
132                break;
133              case 4:
134                region = Region.south;
135                break;
136              default:
137                region = Region.center;
138                break;
139            }
140    
141            add( list.get( i ), region );
142          }
143        }
144      }
145    
146      /**
147       * Add the specified child component to the specified region.
148       *
149       * @param component The child component to add to the layout container.
150       * @param region The region to which the component is to be added.
151       * @throws IllegalArgumentException If a component already exists at the
152       *   specified region index.
153       */
154      public void add( final Component component, final Region region )
155      {
156        if ( regionToIndex.containsKey( region ) )
157        {
158          throw new IllegalArgumentException(
159              "Component " + component + " illegally added to BorderLayout " +
160                  "at region: " + region );
161        }
162    
163        int index = getComponentCount();
164        super.add( component, index );
165        regionToIndex.put( region, index );
166        indexToRegion.put( index, region );
167      }
168    
169      /**
170       * Over-ridden to add the component to {@link Region#center}.
171       *
172       * {@inheritDoc}
173       * @throws IllegalArgumentException If invoked more than once or if the
174       *   index is greater than 0.
175       */
176      @Override
177      public void add( final Component component, final int index )
178          throws IllegalChildException
179      {
180        if ( index > 0 )
181        {
182          throw new IllegalArgumentException(
183              "Component " + component + " illegally added to BorderLayout " +
184                  "at region: center" );
185        }
186    
187        add( component, Region.center );
188      }
189    
190      /**
191       * Over-ridden to add the component to {@link Region#center}.
192       *
193       * {@inheritDoc}
194       * @throws IllegalArgumentException If invoked more than once.
195       */
196      @Override
197      public void add( final Component component )
198      {
199        add( component, Region.center );
200      }
201    
202      /**
203       * Return the child component for the specified region.
204       *
205       * @param region The region for which the child component is to be retrieved.
206       * @return Returns the child component or {@code null} if no child exists.
207       */
208      public Component getComponent( final Region region )
209      {
210        if ( ! regionToIndex.containsKey( region ) ) return null;
211        return getComponent( regionToIndex.get( region ) );
212      }
213    
214      /**
215       * Over-ridden to clear the maps used to maintain region to child index
216       * relationships.
217       *
218       * {@inheritDoc}
219       */
220      @Override
221      public void dispose()
222      {
223        regionToIndex.clear();
224        indexToRegion.clear();
225        super.dispose();
226      }
227    
228      /**
229       * Return the mappings for the region to child index.
230       *
231       * @return The map with the region as key.
232       */
233      Map<Region,Integer> getRegionToIndex()
234      {
235        return regionToIndex;
236      }
237    
238      /**
239       * Return the mappings for the child index to region.
240       *
241       * @return The map with the child index as key
242       */
243      Map<Integer,Region> getIndexToRegion()
244      {
245        return indexToRegion;
246      }
247    }