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 26 package javax.swing; 27 28 import java.awt.AWTError; 29 import java.awt.LayoutManager; 30 import java.awt.Component; 31 import java.awt.Container; 32 import java.awt.Rectangle; 33 import java.awt.Point; 34 import java.awt.Dimension; 35 import java.awt.Insets; 36 import java.io.Serializable; 37 38 /** 39 * The default layout manager for <code>JViewport</code>. 40 * <code>ViewportLayout</code> defines 41 * a policy for layout that should be useful for most applications. 42 * The viewport makes its view the same size as the viewport, 43 * however it will not make the view smaller than its minimum size. 44 * As the viewport grows the view is kept bottom justified until 45 * the entire view is visible, subsequently the view is kept top 46 * justified. 47 * <p> 48 * <strong>Warning:</strong> 49 * Serialized objects of this class will not be compatible with 50 * future Swing releases. The current serialization support is 51 * appropriate for short term storage or RMI between applications running 52 * the same version of Swing. As of 1.4, support for long term storage 53 * of all JavaBeans™ 54 * has been added to the <code>java.beans</code> package. 55 * Please see {@link java.beans.XMLEncoder}. 56 * 57 * @author Hans Muller 58 * @since 1.2 59 */ 60 @SuppressWarnings("serial") // Same-version serialization only 61 public class ViewportLayout implements LayoutManager, Serializable 62 { 63 // Single instance used by JViewport. 64 static ViewportLayout SHARED_INSTANCE = new ViewportLayout(); 65 66 /** 67 * Adds the specified component to the layout. Not used by this class. 68 * @param name the name of the component 69 * @param c the component to be added 70 */ 71 public void addLayoutComponent(String name, Component c) { } 72 73 /** 74 * Removes the specified component from the layout. Not used by 75 * this class. 76 * @param c the component to remove 77 */ 78 public void removeLayoutComponent(Component c) { } 79 80 81 /** 82 * Returns the preferred dimensions for this layout given the components 83 * in the specified target container. 84 * @param parent the component which needs to be laid out 85 * @return a <code>Dimension</code> object containing the 86 * preferred dimensions 87 * @see #minimumLayoutSize 88 */ 89 public Dimension preferredLayoutSize(Container parent) { 90 Component view = ((JViewport)parent).getView(); 91 if (view == null) { 92 return new Dimension(0, 0); 93 } 94 else if (view instanceof Scrollable) { 95 return ((Scrollable)view).getPreferredScrollableViewportSize(); 96 } 97 else { 98 return view.getPreferredSize(); 99 } 100 } 101 102 103 /** 104 * Returns the minimum dimensions needed to layout the components 105 * contained in the specified target container. 106 * 107 * @param parent the component which needs to be laid out 108 * @return a <code>Dimension</code> object containing the minimum 109 * dimensions 110 * @see #preferredLayoutSize 111 */ 112 public Dimension minimumLayoutSize(Container parent) { 113 return new Dimension(4, 4); 114 } 115 116 117 /** 118 * Called by the AWT when the specified container needs to be laid out. 119 * 120 * @param parent the container to lay out 121 * 122 * @throws AWTError if the target isn't the container specified to the 123 * <code>BoxLayout</code> constructor 124 */ 125 public void layoutContainer(Container parent) 126 { 127 JViewport vp = (JViewport)parent; 128 Component view = vp.getView(); 129 Scrollable scrollableView = null; 130 131 if (view == null) { 132 return; 133 } 134 else if (view instanceof Scrollable) { 135 scrollableView = (Scrollable) view; 136 } 137 138 /* All of the dimensions below are in view coordinates, except 139 * vpSize which we're converting. 140 */ 141 142 Insets insets = vp.getInsets(); 143 Dimension viewPrefSize = view.getPreferredSize(); 144 Dimension vpSize = vp.getSize(); 145 Dimension extentSize = vp.toViewCoordinates(vpSize); 146 Dimension viewSize = new Dimension(viewPrefSize); 147 148 if (scrollableView != null) { 149 if (scrollableView.getScrollableTracksViewportWidth()) { 150 viewSize.width = vpSize.width; 151 } 152 if (scrollableView.getScrollableTracksViewportHeight()) { 153 viewSize.height = vpSize.height; 154 } 155 } 156 157 Point viewPosition = vp.getViewPosition(); 158 159 /* If the new viewport size would leave empty space to the 160 * right of the view, right justify the view or left justify 161 * the view when the width of the view is smaller than the 162 * container. 163 */ 164 if (scrollableView == null || 165 vp.getParent() == null || 166 vp.getParent().getComponentOrientation().isLeftToRight()) { 167 if ((viewPosition.x + extentSize.width) > viewSize.width) { 168 viewPosition.x = Math.max(0, viewSize.width - extentSize.width); 169 } 170 } else { 171 if (extentSize.width > viewSize.width) { 172 viewPosition.x = viewSize.width - extentSize.width; 173 } else { 174 viewPosition.x = Math.max(0, Math.min(viewSize.width - extentSize.width, viewPosition.x)); 175 } 176 } 177 178 /* If the new viewport size would leave empty space below the 179 * view, bottom justify the view or top justify the view when 180 * the height of the view is smaller than the container. 181 */ 182 if ((viewPosition.y + extentSize.height) > viewSize.height) { 183 viewPosition.y = Math.max(0, viewSize.height - extentSize.height); 184 } 185 186 /* If we haven't been advised about how the viewports size 187 * should change wrt to the viewport, i.e. if the view isn't 188 * an instance of Scrollable, then adjust the views size as follows. 189 * 190 * If the origin of the view is showing and the viewport is 191 * bigger than the views preferred size, then make the view 192 * the same size as the viewport. 193 */ 194 if (scrollableView == null) { 195 if ((viewPosition.x == 0) && (vpSize.width > viewPrefSize.width)) { 196 viewSize.width = vpSize.width; 197 } 198 if ((viewPosition.y == 0) && (vpSize.height > viewPrefSize.height)) { 199 viewSize.height = vpSize.height; 200 } 201 } 202 vp.setViewPosition(viewPosition); 203 vp.setViewSize(viewSize); 204 } 205 }