5 * A ToolbarLayout arranges components in a left-to-right flow, much
6 * like the FlowLayout which is supplied with the JDK. However, it
7 * fixes the problem with the FlowLayout that occurs when a FlowLayout
8 * is for a North aligned component of a BorderLayout--namely, that
9 * if the window is shrunk so that some of the components within the
10 * FlowLayout wrap to the next line the component does not grow in
11 * height to support this wrapping. This bug was caused by the library
12 * designers using the preferred size in recalculating, not the size
13 * which is determined by the window width. As such, the flow layout
14 * would always want to be the height of one row.
16 * A ToolbarLayout lets each component assume its natural (preferred) size.
18 * NOTE: This class was initially a subclass of FlowLayout, but we
19 * encountered problems using that approach.
21 * @version 0.10, 1999-04-27
22 * @author Peter Armstrong
23 * @author Tony Johnson
25 public class ToolbarLayout implements LayoutManager, java.io.Serializable {
28 * This value indicates that each row of components
29 * should be left-justified.
31 public static final int LEFT = 0;
34 * This value indicates that each row of components
37 public static final int CENTER = 1;
40 * This value indicates that each row of components
41 * should be right-justified.
43 public static final int RIGHT = 2;
51 * Constructs a new ToolbarLayout with a left alignment and a
52 * default 5-unit horizontal and vertical gap.
54 public ToolbarLayout() {
59 * Constructs a new ToolbarLayout with the specified alignment and a
60 * default 5-unit horizontal and vertical gap.
61 * The value of the alignment argument must be one of
62 * <code>ToolbarLayout.LEFT</code>, <code>ToolbarLayout.RIGHT</code>,
63 * or <code>ToolbarLayout.CENTER</code>.
64 * @param align the alignment value
66 public ToolbarLayout(int align) {
71 * Creates a new ToolbarLayout with the indicated alignment
72 * and the indicated horizontal and vertical gaps.
74 * The value of the alignment argument must be one of
75 * <code>ToolbarLayout.LEFT</code>, <code>ToolbarLayout.RIGHT</code>,
76 * or <code>ToolbarLayout.CENTER</code>.
77 * @param align the alignment value.
78 * @param hgap the horizontal gap between components.
79 * @param vgap the vertical gap between components.
81 public ToolbarLayout(int align, int hgap, int vgap) {
88 * Gets the alignment for this layout.
89 * Possible values are <code>ToolbarLayout.LEFT</code>,
90 * <code>ToolbarLayout.RIGHT</code>, or <code>ToolbarLayout.CENTER</code>.
91 * @return the alignment value for this layout.
92 * @see ToolbarLayout#setAlignment
94 public int getAlignment() {
99 * Sets the alignment for this layout.
100 * Possible values are <code>ToolbarLayout.LEFT</code>,
101 * <code>ToolbarLayout.RIGHT</code>, and <code>ToolbarLayout.CENTER</code>.
102 * @param align the alignment value.
103 * @see ToolbarLayout#getAlignment
105 public void setAlignment(int align) {
110 * Gets the horizontal gap between components.
111 * @return the horizontal gap between components.
112 * @see ToolbarLayout#setHgap
114 public int getHgap() {
119 * Sets the horizontal gap between components.
120 * @param hgap the horizontal gap between components
121 * @see ToolbarLayout#getHgap
123 public void setHgap(int hgap) {
128 * Gets the vertical gap between components.
129 * @return the vertical gap between components.
130 * @see ToolbarLayout#setVgap
132 public int getVgap() {
137 * Sets the vertical gap between components.
138 * @param vgap the vertical gap between components
139 * @see ToolbarLayout#getVgap
141 public void setVgap(int vgap) {
146 * Adds the specified component to the layout. Sets the orientation to be horizontal.
147 * @param name the name of the component
148 * @param comp the component to be added
150 public void addLayoutComponent(String name, Component comp) {
154 * Removes the specified component from the layout. Not used by
156 * @param comp the component to remove
157 * @see java.awt.Container#removeAll
159 public void removeLayoutComponent(Component comp) {
163 * Returns the preferred dimensions for this layout given the components
164 * in the specified target container. This method is the difference
165 * between ToolbarLayout and FlowLayout.
166 * @param target the component which needs to be laid out
167 * @return the preferred dimensions to lay out the
168 * subcomponents of the specified container.
170 * @see #minimumLayoutSize
171 * @see java.awt.Container#getPreferredSize
173 public Dimension preferredLayoutSize(Container target) {
174 synchronized (target.getTreeLock()) {
175 Dimension dim = new Dimension(0, 0);
176 int nmembers = target.getComponentCount();
178 Insets insets = target.getInsets();
180 int numRows = 1; //the number of rows
181 int rowSumWidth = insets.left + insets.right; //the width of the row so far
182 int rowMaxWidth = target.getSize().width; //the width that the ToolbarLayout is in
183 int rowHeight = 0; //the height of each row
184 int numOnRow = 0; //the number of components on the row
186 for (int i = 0 ; i < nmembers ; i++) {
187 Component m = target.getComponent(i);
189 Dimension d = m.getPreferredSize();
190 rowHeight = Math.max(rowHeight, d.height); //make each row the height of the biggest component of all
192 rowSumWidth += hgap;//add on the pre-spacing if this is not the first component
194 rowSumWidth += d.width; //add the width of the component
196 //if it overflowed and if there are components already on this row then bump this component to next row
197 if ((rowSumWidth + hgap) > rowMaxWidth) {
200 rowSumWidth = insets.left + insets.right + d.width;
201 numOnRow = 0;//reset the number of components on the next row (we ++ no matter what later)
204 numOnRow++;//add this component to the count of the number on the row
207 dim.width = rowMaxWidth;
208 dim.height = insets.top + insets.bottom + numRows*rowHeight + vgap*(numRows + 1);
214 * Returns the minimum dimensions needed to layout the components
215 * contained in the specified target container.
216 * @param target the component which needs to be laid out
217 * @return the minimum dimensions to lay out the
218 * subcomponents of the specified container.
219 * @see #preferredLayoutSize
220 * @see java.awt.Container
221 * @see java.awt.Container#doLayout
223 public Dimension minimumLayoutSize(Container target) {
224 synchronized (target.getTreeLock()) {
225 Dimension dim = new Dimension(0, 0);
226 int nmembers = target.getComponentCount();
228 for (int i = 0 ; i < nmembers ; i++) {
229 Component m = target.getComponent(i);
231 Dimension d = m.getMinimumSize();
232 dim.height = Math.max(dim.height, d.height);
236 dim.width += d.width;
239 Insets insets = target.getInsets();
240 dim.width += insets.left + insets.right + hgap*2;
241 dim.height += insets.top + insets.bottom + vgap*2;
247 * Centers the elements in the specified row, if there is any slack.
248 * @param target the component which needs to be moved
249 * @param x the x coordinate
250 * @param y the y coordinate
251 * @param width the width dimensions
252 * @param height the height dimensions
253 * @param rowStart the beginning of the row
254 * @param rowEnd the the ending of the row
256 private void moveComponents(Container target, int x, int y, int width, int height, int rowStart, int rowEnd) {
257 synchronized (target.getTreeLock()) {
268 for (int i = rowStart ; i < rowEnd ; i++) {
269 Component m = target.getComponent(i);
271 m.setLocation(x, y + (height - m.size().height) / 2);
272 x += hgap + m.size().width;
279 * Lays out the container. This method lets each component take
280 * its preferred size by reshaping the components in the
281 * target container in order to satisfy the constraints of
282 * this <code>ToolbarLayout</code> object.
283 * @param target the specified component being laid out.
285 * @see java.awt.Container#doLayout
287 public void layoutContainer(Container target) {
288 synchronized (target.getTreeLock()) {
289 Insets insets = target.getInsets();
290 int maxwidth = target.size().width - (insets.left + insets.right + hgap*2);
291 int nmembers = target.getComponentCount();
292 int x = 0, y = insets.top + vgap;
293 int rowh = 0, start = 0;
295 for (int i = 0 ; i < nmembers ; i++) {
296 Component m = target.getComponent(i);
298 Dimension d = m.getPreferredSize();
299 m.setSize(d.width, d.height);
300 if ((x == 0) || ((x + d.width) <= maxwidth)) {
305 rowh = Math.max(rowh, d.height);
307 moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, i);
315 moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, nmembers);
320 * Returns a string representation of this <code>ToolbarLayout</code>
321 * object and its values.
322 * @return a string representation of this layout.
324 public String toString() {
327 case LEFT: str = ",align=left"; break;
328 case CENTER: str = ",align=center"; break;
329 case RIGHT: str = ",align=right"; break;
331 return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";