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