001 
002 /*
003  *  JScripter Standard 1.0 - To Script In Java
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package jsx.ui.layout;
021 
022 import js.ArrayLike;
023 import js.Initializer;
024 import js.Js;
025 import js.ObjectLike;
026 import js.Vars;
027 import jsx.ui.Component;
028 import jsx.ui.Container;
029 import jsx.ui.Widget;
030 
031 /**
032  * <p>Defines border layout managers.</p>
033  * <p>A {@link BorderLayout} is composed of {@link BarLayout} layouts. It arranges and 
034  * resizes the first two children to fit into the north and south borders of the 
035  * container and then fits the third and fourth children to the west and east borders 
036  * of the rest area. Finally it fits the fifth child to the rest area and ignores any 
037  * other children the container may have. An undefined child is silently ignored and 
038  * leaves that region for others to fill.</p>
039  * <p>The widgets are laid out according to their preferred sizes and the constraints of 
040  * the container's size. The north and south widgets may be stretched horizontally; the 
041  * west and east widgets may be stretched vertically; the center widget may stretch both 
042  * horizontally and vertically to fill any space left over.</p>
043  * 
044  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
045  */
046 public final class BorderLayout extends AbsoluteLayout
047 {
048     /**
049      * <p>An integer constant that indicates an array index of the "north" widget in 
050      * the children list of the container a {@link BorderLayout} is laying out.</p>
051      * @since 1.0
052      */
053     public final static int NORTH  = 0;
054     /**
055      * <p>An integer constant that indicates an array index of the "south" widget in 
056      * the children list of the container a {@link BorderLayout} is laying out.</p>
057      * @since 1.0
058      */
059     public final static int SOUTH  = 1;
060     /**
061      * <p>An integer constant that indicates an array index of the "west" widget in 
062      * the children list of the container a {@link BorderLayout} is laying out.</p>
063      * @since 1.0
064      */
065     public final static int WEST   = 2;
066     /**
067      * <p>An integer constant that indicates an array index of the "east" widget in 
068      * the children list of the container a {@link BorderLayout} is laying out.</p>
069      * @since 1.0
070      */
071     public final static int EAST   = 3;
072     /**
073      * <p>An integer constant that indicates an array index of the "center" widget in 
074      * the children list of the container a {@link BorderLayout} is laying out.</p>
075      * @since 1.0
076      */
077     public final static int CENTER = 4;
078 
079     /**
080      * <p>The default constructor that constructs a layout manager of this type.</p>
081      * <p>This constructor invokes the default constructor of the superclass.</p>
082      * @since 1.0
083      * @see #BorderLayout(ObjectLike)
084      */
085     public BorderLayout() {}
086 
087     /**
088      * <p>A typical constructor that constructs a layout manager of this type and forces 
089      * constructors of subclasses to pass initializing data.</p>
090      * <p>This constructor invokes the typical constructor of the superclass passing 
091      * the specified initializing object as the argument.</p>
092      * @param ini The initializing object.
093      * @since 1.0
094      * @see #BorderLayout()
095      */
096     public BorderLayout(ObjectLike ini) {
097         super(ini);
098     }
099 
100     /**
101      * <p>Layouts a container.</p>
102      * <p>This method is implemented with {@link BarLayout}. It fits the first five 
103      * children to the north, south, west and east regions around the border of the 
104      * container and then fits the fifth child to the rest area ignoring any other 
105      * children the container may have. A <tt>null</tt> child is silently ignored but 
106      * leaves that region for others to fill.</p>
107      * <p>It lays out the child widgets according to their preferred sizes and the 
108      * constraints of the size of the container. The north and south widgets may be 
109      * stretched horizontally while the west and east widgets may be stretched 
110      * vertically. The center widget may stretch both dimensions to fill any space 
111      * left over.</p>
112      * @param c The container to layout.
113      * @since 1.0
114      */
115     @Override
116     protected void doLayout(Container c) {
117         c.detach();
118         Container n = new Container(c.unwrap());
119         ArrayLike<Widget> children = ini(c).var(Container.CHILDREN);
120         n = addBorder(
121                 n,
122                 children.get(NORTH),
123                 new BarLayout(new Initializer().set(
124                         BarLayout.VERTICAL, true
125                 ).set(
126                         BarLayout.ALIGN, true
127                 ).set(
128                         BarLayout.FIT, true
129                 ).var())
130         );
131         n = addBorder(
132                 n,
133                 children.get(SOUTH),
134                 new BarLayout(new Initializer().set(
135                         BarLayout.VERTICAL, true
136                 ).set(
137                         BarLayout.ALIGN, true
138                 ).set(
139                         BarLayout.FIT, true
140                 ).set(
141                         BarLayout.ORIGIN, BarLayout.LEFTBOTTOM
142                 ).var())
143         );
144         n = addBorder(
145                 n,
146                 children.get(WEST),
147                 new BarLayout(new Initializer().set(
148                         BarLayout.ALIGN, true
149                 ).set(
150                         BarLayout.FIT, true
151                 ).var())
152         );
153         n = addBorder(
154                 n,
155                 children.get(EAST),
156                 new BarLayout(new Initializer().set(
157                         BarLayout.ALIGN, true
158                 ).set(
159                         BarLayout.FIT, true
160                 ).set(
161                         BarLayout.ORIGIN, BarLayout.RIGHTTOP
162                 ).var())
163         );
164         Widget w = children.get(CENTER);
165         if (Js.be(w)) {
166             n.setLayout(
167                     new BarLayout(new Initializer().set(
168                             BarLayout.ALIGN, true
169                     ).set(
170                             BarLayout.FIT, true
171                     ).var())
172             );
173             n.add(new Widget(w.unwrap()));
174         }
175     } 
176 
177     private static final Container addBorder(Container p, Widget w, Container.Layout u) {
178         if (Js.be(w)) {
179             p.setLayout(u);
180             Container n = new Container();
181             Component c = w.unwrap();
182             p.add(new Vars<Widget>().add(new Widget(c)).add(n).var());
183             return n;
184         }
185         return p;
186     }
187 }