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