1 /* 2 * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package sun.awt; 26 27 import java.awt.*; 28 29 /** 30 * Extends the FlowLayout class to support both vertical and horizontal 31 * layout of components. Orientation can be changed dynamically after 32 * creation by calling either of the methods @method orientHorizontally or 33 * @method orientVertically. Separate values for alignment, vertical gap, 34 * and horizontal gap can be specified for horizontal and vertical 35 * orientation. 36 * 37 * @author Terry Cline 38 */ 39 public class OrientableFlowLayout extends FlowLayout { 40 /** 41 * The horizontal orientation constant. 42 */ 43 public static final int HORIZONTAL = 0; 44 45 /** 46 * The vertical orientation constant. 47 */ 48 public static final int VERTICAL = 1; 49 50 /** 51 * The top vertical alignment constant. 52 */ 53 public static final int TOP = 0; 54 55 /** 56 * The bottom vertical alignment constant. 57 */ 58 public static final int BOTTOM = 2; // CENTER == 1 59 60 int orientation; 61 int vAlign; 62 int vHGap; 63 int vVGap; 64 65 /** 66 * Constructs a new flow layout with a horizontal orientation and 67 * centered alignment. 68 */ 69 public OrientableFlowLayout() { 70 this(HORIZONTAL, CENTER, CENTER, 5, 5, 5, 5); 71 } 72 73 /** 74 * Constructs a new flow layout with the specified orientation and 75 * a centered alignment. 76 * 77 * @param orientation the orientation, one of HORIZONTAL or VERTICAL. 78 */ 79 public OrientableFlowLayout(int orientation) { 80 this(orientation, CENTER, CENTER, 5, 5, 5, 5); 81 } 82 83 /** 84 * Constructs a new flow layout with the specified orientation and 85 * alignment. 86 * 87 * @param orientation the orientation, one of HORIZONTAL or VERTICAL. 88 * @param hAlign the horizontal alignment, one of LEFT, CENTER, or RIGHT. 89 * @param vAlign the vertical alignment, one of TOP, CENTER, or BOTTOM. 90 */ 91 public OrientableFlowLayout(int orientation, int hAlign, int vAlign) { 92 this(orientation, hAlign, vAlign, 5, 5, 5, 5); 93 } 94 95 /** 96 * Constructs a new flow layout with the specified orientation, 97 * alignment, and gap values. 98 * 99 * @param orientation the orientation, one of HORIZONTAL or VERTICAL. 100 * @param hAlign the horizontal alignment, one of LEFT, CENTER, or RIGHT. 101 * @param vAlign the vertical alignment, one of TOP, CENTER, or BOTTOM. 102 * @param hHGap the horizontal gap between components in HORIZONTAL. 103 * @param hVGap the vertical gap between components in HORIZONTAL. 104 * @param vHGap the horizontal gap between components in VERTICAL. 105 * @param vVGap the vertical gap between components in VERTICAL. 106 */ 107 public OrientableFlowLayout(int orientation, int hAlign, int vAlign, int hHGap, int hVGap, int vHGap, int vVGap) { 108 super(hAlign, hHGap, hVGap); 109 this.orientation = orientation; 110 this.vAlign = vAlign; 111 this.vHGap = vHGap; 112 this.vVGap = vVGap; 113 } 114 115 /** 116 * Set the layout's current orientation to horizontal. 117 */ 118 public synchronized void orientHorizontally() { 119 orientation = HORIZONTAL; 120 } 121 122 /** 123 * Set the layout's current orientation to vertical. 124 */ 125 public synchronized void orientVertically() { 126 orientation = VERTICAL; 127 } 128 129 /** 130 * Returns the preferred dimensions for this layout given the 131 * components in the specified target container. 132 * 133 * @param target the component which needs to be laid out. 134 * @see Container 135 * @see FlowLayout 136 * @see #minimumLayoutSize 137 */ 138 public Dimension preferredLayoutSize(Container target) { 139 if (orientation == HORIZONTAL) { 140 return super.preferredLayoutSize(target); 141 } 142 else { 143 Dimension dim = new Dimension(0, 0); 144 145 int n = target.countComponents(); 146 for (int i = 0; i < n; i++) { 147 Component c = target.getComponent(i); 148 if (c.isVisible()) { 149 Dimension cDim = c.preferredSize(); 150 dim.width = Math.max(dim.width, cDim.width); 151 if (i > 0) { 152 dim.height += vVGap; 153 } 154 dim.height += cDim.height; 155 } 156 } 157 158 Insets insets = target.insets();; 159 dim.width += insets.left + insets.right + vHGap*2; 160 dim.height += insets.top + insets.bottom + vVGap*2; 161 162 return dim; 163 } 164 } 165 166 /** 167 * Returns the minimum dimensions needed to layout the components 168 * contained in the specified target container. 169 * 170 * @param target the component which needs to be laid out. 171 * @see #preferredLayoutSize. 172 */ 173 public Dimension minimumLayoutSize(Container target) { 174 if (orientation == HORIZONTAL) { 175 return super.minimumLayoutSize(target); 176 } 177 else { 178 Dimension dim = new Dimension(0, 0); 179 180 int n = target.countComponents(); 181 for (int i = 0; i < n; i++) { 182 Component c = target.getComponent(i); 183 if (c.isVisible()) { 184 Dimension cDim = c.minimumSize(); 185 dim.width = Math.max(dim.width, cDim.width); 186 if (i > 0) { 187 dim.height += vVGap; 188 } 189 dim.height += cDim.height; 190 } 191 } 192 193 Insets insets = target.insets(); 194 dim.width += insets.left + insets.right + vHGap*2; 195 dim.height += insets.top + insets.bottom + vVGap*2; 196 197 return dim; 198 } 199 } 200 201 /** 202 * Lays out the container. This method will reshape the 203 * components in the target to satisfy the constraints of the 204 * layout. 205 * 206 * @param target the specified component being laid out. 207 * @see Container. 208 */ 209 public void layoutContainer(Container target) { 210 if (orientation == HORIZONTAL) { 211 super.layoutContainer(target); 212 } 213 else { 214 Insets insets = target.insets(); 215 Dimension targetDim = target.size(); 216 int maxHeight = targetDim.height - (insets.top + insets.bottom + vVGap*2); 217 int x = insets.left + vHGap; 218 int y = 0; 219 int colWidth = 0; 220 int start = 0; 221 222 int n = target.countComponents(); 223 for (int i = 0; i < n; i++) { 224 Component c = target.getComponent(i); 225 if (c.isVisible()) { 226 Dimension cDim = c.preferredSize(); 227 c.resize(cDim.width, cDim.height); 228 229 if ((y == 0) || ((y + cDim.height) <= maxHeight)) { 230 if (y > 0) { 231 y += vVGap; 232 } 233 y += cDim.height; 234 colWidth = Math.max(colWidth, cDim.width); 235 } 236 else { 237 moveComponents(target, 238 x, 239 insets.top + vVGap, 240 colWidth, 241 maxHeight - y, 242 start, 243 i); 244 x += vHGap + colWidth; 245 y = cDim.width; 246 colWidth = cDim.width; 247 start = i; 248 } 249 } 250 } 251 252 moveComponents(target, 253 x, 254 insets.top + vVGap, 255 colWidth, 256 maxHeight - y, 257 start, 258 n); 259 } 260 } 261 262 /** 263 * Aligns the components vertically if there is any slack. 264 * 265 * @param target the container whose components need to be moved. 266 * @param x the x coordinate. 267 * @param y the y coordinate. 268 * @param width the width available. 269 * @param height the height available. 270 * @param colStart the beginning of the column. 271 * @param colEnd the end of the column. 272 */ 273 private void moveComponents(Container target, int x, int y, int width, int height, int colStart, int colEnd) { 274 switch (vAlign) { 275 case TOP: 276 break; 277 case CENTER: 278 y += height/2; 279 break; 280 case BOTTOM: 281 y += height; 282 } 283 284 for (int i = colStart; i < colEnd; i++) { 285 Component c = target.getComponent(i); 286 Dimension cDim = c.size(); 287 if (c.isVisible()) { 288 c.move(x + (width - cDim.width)/2, y); 289 y += vVGap + cDim.height; 290 } 291 } 292 } 293 294 /** 295 * Returns the String representation of this layout's values. 296 */ 297 public String toString() { 298 String str = ""; 299 switch (orientation) { 300 case HORIZONTAL: 301 str = "orientation=horizontal, "; 302 break; 303 case VERTICAL: 304 str = "orientation=vertical, "; 305 break; 306 } 307 308 return getClass().getName() + "[" + str + super.toString() + "]"; 309 } 310 }