1 /* 2 * Copyright (c) 1997, 2014, 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 javax.swing; 26 27 28 import java.awt.*; 29 import java.beans.ConstructorProperties; 30 import java.io.Serializable; 31 32 /** 33 * A layout manager to arrange components over the top 34 * of each other. The requested size of the container 35 * will be the largest requested size of the children, 36 * taking alignment needs into consideration. 37 * 38 * The alignment is based upon what is needed to properly 39 * fit the children in the allocation area. The children 40 * will be placed such that their alignment points are all 41 * on top of each other. 42 * <p> 43 * <strong>Warning:</strong> 44 * Serialized objects of this class will not be compatible with 45 * future Swing releases. The current serialization support is 46 * appropriate for short term storage or RMI between applications running 47 * the same version of Swing. As of 1.4, support for long term storage 48 * of all JavaBeans™ 49 * has been added to the <code>java.beans</code> package. 50 * Please see {@link java.beans.XMLEncoder}. 51 * 52 * @author Timothy Prinzing 53 */ 54 @SuppressWarnings("serial") // Same-version serialization only 55 public class OverlayLayout implements LayoutManager2,Serializable { 56 57 /** 58 * Constructs a layout manager that performs overlay 59 * arrangement of the children. The layout manager 60 * created is dedicated to the given container. 61 * 62 * @param target the container to do layout against 63 */ 64 @ConstructorProperties({"target"}) 65 public OverlayLayout(Container target) { 66 this.target = target; 67 } 68 69 /** 70 * Returns the container that uses this layout manager. 71 * 72 * @return the container that uses this layout manager 73 * 74 * @since 1.6 75 */ 76 public final Container getTarget() { 77 return this.target; 78 } 79 80 /** 81 * Indicates a child has changed its layout related information, 82 * which causes any cached calculations to be flushed. 83 * 84 * @param target the container 85 */ 86 public void invalidateLayout(Container target) { 87 checkContainer(target); 88 xChildren = null; 89 yChildren = null; 90 xTotal = null; 91 yTotal = null; 92 } 93 94 /** 95 * Adds the specified component to the layout. Used by 96 * this class to know when to invalidate layout. 97 * 98 * @param name the name of the component 99 * @param comp the the component to be added 100 */ 101 public void addLayoutComponent(String name, Component comp) { 102 invalidateLayout(comp.getParent()); 103 } 104 105 /** 106 * Removes the specified component from the layout. Used by 107 * this class to know when to invalidate layout. 108 * 109 * @param comp the component to remove 110 */ 111 public void removeLayoutComponent(Component comp) { 112 invalidateLayout(comp.getParent()); 113 } 114 115 /** 116 * Adds the specified component to the layout, using the specified 117 * constraint object. Used by this class to know when to invalidate 118 * layout. 119 * 120 * @param comp the component to be added 121 * @param constraints where/how the component is added to the layout. 122 */ 123 public void addLayoutComponent(Component comp, Object constraints) { 124 invalidateLayout(comp.getParent()); 125 } 126 127 /** 128 * Returns the preferred dimensions for this layout given the components 129 * in the specified target container. Recomputes the layout if it 130 * has been invalidated. Factors in the current inset setting returned 131 * by getInsets(). 132 * 133 * @param target the component which needs to be laid out 134 * @return a Dimension object containing the preferred dimensions 135 * @see #minimumLayoutSize 136 */ 137 public Dimension preferredLayoutSize(Container target) { 138 checkContainer(target); 139 checkRequests(); 140 141 Dimension size = new Dimension(xTotal.preferred, yTotal.preferred); 142 Insets insets = target.getInsets(); 143 size.width += insets.left + insets.right; 144 size.height += insets.top + insets.bottom; 145 return size; 146 } 147 148 /** 149 * Returns the minimum dimensions needed to lay out the components 150 * contained in the specified target container. Recomputes the layout 151 * if it has been invalidated, and factors in the current inset setting. 152 * 153 * @param target the component which needs to be laid out 154 * @return a Dimension object containing the minimum dimensions 155 * @see #preferredLayoutSize 156 */ 157 public Dimension minimumLayoutSize(Container target) { 158 checkContainer(target); 159 checkRequests(); 160 161 Dimension size = new Dimension(xTotal.minimum, yTotal.minimum); 162 Insets insets = target.getInsets(); 163 size.width += insets.left + insets.right; 164 size.height += insets.top + insets.bottom; 165 return size; 166 } 167 168 /** 169 * Returns the maximum dimensions needed to lay out the components 170 * contained in the specified target container. Recomputes the 171 * layout if it has been invalidated, and factors in the inset setting 172 * returned by <code>getInset</code>. 173 * 174 * @param target the component that needs to be laid out 175 * @return a <code>Dimension</code> object containing the maximum 176 * dimensions 177 * @see #preferredLayoutSize 178 */ 179 public Dimension maximumLayoutSize(Container target) { 180 checkContainer(target); 181 checkRequests(); 182 183 Dimension size = new Dimension(xTotal.maximum, yTotal.maximum); 184 Insets insets = target.getInsets(); 185 size.width += insets.left + insets.right; 186 size.height += insets.top + insets.bottom; 187 return size; 188 } 189 190 /** 191 * Returns the alignment along the x axis for the container. 192 * 193 * @param target the container 194 * @return the alignment >= 0.0f && <= 1.0f 195 */ 196 public float getLayoutAlignmentX(Container target) { 197 checkContainer(target); 198 checkRequests(); 199 return xTotal.alignment; 200 } 201 202 /** 203 * Returns the alignment along the y axis for the container. 204 * 205 * @param target the container 206 * @return the alignment >= 0.0f && <= 1.0f 207 */ 208 public float getLayoutAlignmentY(Container target) { 209 checkContainer(target); 210 checkRequests(); 211 return yTotal.alignment; 212 } 213 214 /** 215 * Called by the AWT when the specified container needs to be laid out. 216 * 217 * @param target the container to lay out 218 * 219 * @exception AWTError if the target isn't the container specified to the 220 * constructor 221 */ 222 public void layoutContainer(Container target) { 223 checkContainer(target); 224 checkRequests(); 225 226 int nChildren = target.getComponentCount(); 227 int[] xOffsets = new int[nChildren]; 228 int[] xSpans = new int[nChildren]; 229 int[] yOffsets = new int[nChildren]; 230 int[] ySpans = new int[nChildren]; 231 232 // determine the child placements 233 Dimension alloc = target.getSize(); 234 Insets in = target.getInsets(); 235 alloc.width -= in.left + in.right; 236 alloc.height -= in.top + in.bottom; 237 SizeRequirements.calculateAlignedPositions(alloc.width, xTotal, 238 xChildren, xOffsets, 239 xSpans); 240 SizeRequirements.calculateAlignedPositions(alloc.height, yTotal, 241 yChildren, yOffsets, 242 ySpans); 243 244 // flush changes to the container 245 for (int i = 0; i < nChildren; i++) { 246 Component c = target.getComponent(i); 247 c.setBounds(in.left + xOffsets[i], in.top + yOffsets[i], 248 xSpans[i], ySpans[i]); 249 } 250 } 251 252 void checkContainer(Container target) { 253 if (this.target != target) { 254 throw new AWTError("OverlayLayout can't be shared"); 255 } 256 } 257 258 void checkRequests() { 259 if (xChildren == null || yChildren == null) { 260 // The requests have been invalidated... recalculate 261 // the request information. 262 int n = target.getComponentCount(); 263 xChildren = new SizeRequirements[n]; 264 yChildren = new SizeRequirements[n]; 265 for (int i = 0; i < n; i++) { 266 Component c = target.getComponent(i); 267 Dimension min = c.getMinimumSize(); 268 Dimension typ = c.getPreferredSize(); 269 Dimension max = c.getMaximumSize(); 270 xChildren[i] = new SizeRequirements(min.width, typ.width, 271 max.width, 272 c.getAlignmentX()); 273 yChildren[i] = new SizeRequirements(min.height, typ.height, 274 max.height, 275 c.getAlignmentY()); 276 } 277 278 xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren); 279 yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren); 280 } 281 } 282 283 private Container target; 284 private SizeRequirements[] xChildren; 285 private SizeRequirements[] yChildren; 286 private SizeRequirements xTotal; 287 private SizeRequirements yTotal; 288 289 }