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 */ 59 @SuppressWarnings("serial") // Same-version serialization only 60 public class ViewportLayout implements LayoutManager, Serializable 61 { 62 // Single instance used by JViewport. 63 static ViewportLayout SHARED_INSTANCE = new ViewportLayout(); 64 65 /** 66 * Adds the specified component to the layout. Not used by this class. 67 * @param name the name of the component 68 * @param c the the component to be added 69 */ 70 public void addLayoutComponent(String name, Component c) { } 71 72 /** 73 * Removes the specified component from the layout. Not used by 74 * this class. 75 * @param c the component to remove 76 */ 77 public void removeLayoutComponent(Component c) { } 78 79 80 /** 81 * Returns the preferred dimensions for this layout given the components 82 * in the specified target container. 83 * @param parent the component which needs to be laid out 84 * @return a <code>Dimension</code> object containing the 85 * preferred dimensions 86 * @see #minimumLayoutSize 87 */ 88 public Dimension preferredLayoutSize(Container parent) { 89 Component view = ((JViewport)parent).getView(); 90 if (view == null) { 91 return new Dimension(0, 0); 92 } 93 else if (view instanceof Scrollable) { 94 return ((Scrollable)view).getPreferredScrollableViewportSize(); 95 } 96 else { 97 return view.getPreferredSize(); 98 } 99 } 100 101 102 /** 103 * Returns the minimum dimensions needed to layout the components 104 * contained in the specified target container. 105 * 106 * @param parent the component which needs to be laid out 107 * @return a <code>Dimension</code> object containing the minimum 108 * dimensions 109 * @see #preferredLayoutSize 110 */ 111 public Dimension minimumLayoutSize(Container parent) { 112 return new Dimension(4, 4); 113 } 114 115 116 /** 117 * Called by the AWT when the specified container needs to be laid out. 118 * 119 * @param parent the container to lay out 120 * 121 * @throws AWTError if the target isn't the container specified to the 122 * <code>BoxLayout</code> constructor 123 */ 124 public void layoutContainer(Container parent) 125 { 126 JViewport vp = (JViewport)parent; 127 Component view = vp.getView(); 128 Scrollable scrollableView = null; 129 130 if (view == null) { 131 return; 132 } 133 else if (view instanceof Scrollable) { 134 scrollableView = (Scrollable) view; 135 } 136 137 /* All of the dimensions below are in view coordinates, except 138 * vpSize which we're converting. 139 */ 140 141 Insets insets = vp.getInsets(); 142 Dimension viewPrefSize = view.getPreferredSize(); 143 Dimension vpSize = vp.getSize(); 144 Dimension extentSize = vp.toViewCoordinates(vpSize); 145 Dimension viewSize = new Dimension(viewPrefSize); 146 147 if (scrollableView != null) { 148 if (scrollableView.getScrollableTracksViewportWidth()) { 149 viewSize.width = vpSize.width; 150 } 151 if (scrollableView.getScrollableTracksViewportHeight()) { 152 viewSize.height = vpSize.height; 153 } 154 } 155 156 Point viewPosition = vp.getViewPosition(); 157 158 /* If the new viewport size would leave empty space to the 159 * right of the view, right justify the view or left justify 160 * the view when the width of the view is smaller than the 161 * container. 162 */ 163 if (scrollableView == null || 164 vp.getParent() == null || 165 vp.getParent().getComponentOrientation().isLeftToRight()) { 166 if ((viewPosition.x + extentSize.width) > viewSize.width) { 167 viewPosition.x = Math.max(0, viewSize.width - extentSize.width); 168 } 169 } else { 170 if (extentSize.width > viewSize.width) { 171 viewPosition.x = viewSize.width - extentSize.width; 172 } else { 173 viewPosition.x = Math.max(0, Math.min(viewSize.width - extentSize.width, viewPosition.x)); 174 } 175 } 176 177 /* If the new viewport size would leave empty space below the 178 * view, bottom justify the view or top justify the view when 179 * the height of the view is smaller than the container. 180 */ 181 if ((viewPosition.y + extentSize.height) > viewSize.height) { 182 viewPosition.y = Math.max(0, viewSize.height - extentSize.height); 183 } 184 185 /* If we haven't been advised about how the viewports size 186 * should change wrt to the viewport, i.e. if the view isn't 187 * an instance of Scrollable, then adjust the views size as follows. 188 * 189 * If the origin of the view is showing and the viewport is 190 * bigger than the views preferred size, then make the view 191 * the same size as the viewport. 192 */ 193 if (scrollableView == null) { 194 if ((viewPosition.x == 0) && (vpSize.width > viewPrefSize.width)) { 195 viewSize.width = vpSize.width; 196 } 197 if ((viewPosition.y == 0) && (vpSize.height > viewPrefSize.height)) { 198 viewSize.height = vpSize.height; 199 } 200 } 201 vp.setViewPosition(viewPosition); 202 vp.setViewSize(viewSize); 203 } 204 }