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 29 import javax.swing.border.*; 30 31 import java.awt.LayoutManager; 32 import java.awt.Component; 33 import java.awt.Container; 34 import java.awt.Rectangle; 35 import java.awt.Dimension; 36 import java.awt.Insets; 37 import java.io.Serializable; 38 39 40 /** 41 * The layout manager used by <code>JScrollPane</code>. 42 * <code>JScrollPaneLayout</code> is 43 * responsible for nine components: a viewport, two scrollbars, 44 * a row header, a column header, and four "corner" components. 45 * <p> 46 * <strong>Warning:</strong> 47 * Serialized objects of this class will not be compatible with 48 * future Swing releases. The current serialization support is 49 * appropriate for short term storage or RMI between applications running 50 * the same version of Swing. As of 1.4, support for long term storage 51 * of all JavaBeans™ 52 * has been added to the <code>java.beans</code> package. 53 * Please see {@link java.beans.XMLEncoder}. 54 * 55 * @see JScrollPane 56 * @see JViewport 57 * 58 * @author Hans Muller 59 * @since 1.2 60 */ 61 @SuppressWarnings("serial") // Same-version serialization only 62 public class ScrollPaneLayout 63 implements LayoutManager, ScrollPaneConstants, Serializable 64 { 65 66 /** 67 * The scrollpane's viewport child. 68 * Default is an empty <code>JViewport</code>. 69 * @see JScrollPane#setViewport 70 */ 71 protected JViewport viewport; 72 73 74 /** 75 * The scrollpane's vertical scrollbar child. 76 * Default is a <code>JScrollBar</code>. 77 * @see JScrollPane#setVerticalScrollBar 78 */ 79 protected JScrollBar vsb; 80 81 82 /** 83 * The scrollpane's horizontal scrollbar child. 84 * Default is a <code>JScrollBar</code>. 85 * @see JScrollPane#setHorizontalScrollBar 86 */ 87 protected JScrollBar hsb; 88 89 90 /** 91 * The row header child. Default is <code>null</code>. 92 * @see JScrollPane#setRowHeader 93 */ 94 protected JViewport rowHead; 95 96 97 /** 98 * The column header child. Default is <code>null</code>. 99 * @see JScrollPane#setColumnHeader 100 */ 101 protected JViewport colHead; 102 103 104 /** 105 * The component to display in the lower left corner. 106 * Default is <code>null</code>. 107 * @see JScrollPane#setCorner 108 */ 109 protected Component lowerLeft; 110 111 112 /** 113 * The component to display in the lower right corner. 114 * Default is <code>null</code>. 115 * @see JScrollPane#setCorner 116 */ 117 protected Component lowerRight; 118 119 120 /** 121 * The component to display in the upper left corner. 122 * Default is <code>null</code>. 123 * @see JScrollPane#setCorner 124 */ 125 protected Component upperLeft; 126 127 128 /** 129 * The component to display in the upper right corner. 130 * Default is <code>null</code>. 131 * @see JScrollPane#setCorner 132 */ 133 protected Component upperRight; 134 135 136 /** 137 * The display policy for the vertical scrollbar. 138 * The default is <code>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED</code>. 139 * <p> 140 * This field is obsolete, please use the <code>JScrollPane</code> field instead. 141 * 142 * @see JScrollPane#setVerticalScrollBarPolicy 143 */ 144 protected int vsbPolicy = VERTICAL_SCROLLBAR_AS_NEEDED; 145 146 147 /** 148 * The display policy for the horizontal scrollbar. 149 * The default is <code>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED</code>. 150 * <p> 151 * This field is obsolete, please use the <code>JScrollPane</code> field instead. 152 * 153 * @see JScrollPane#setHorizontalScrollBarPolicy 154 */ 155 protected int hsbPolicy = HORIZONTAL_SCROLLBAR_AS_NEEDED; 156 157 158 /** 159 * This method is invoked after the ScrollPaneLayout is set as the 160 * LayoutManager of a <code>JScrollPane</code>. 161 * It initializes all of the internal fields that 162 * are ordinarily set by <code>addLayoutComponent</code>. For example: 163 * <pre> 164 * ScrollPaneLayout mySPLayout = new ScrollPanelLayout() { 165 * public void layoutContainer(Container p) { 166 * super.layoutContainer(p); 167 * // do some extra work here ... 168 * } 169 * }; 170 * scrollpane.setLayout(mySPLayout): 171 * </pre> 172 * 173 * @param sp an instance of the {@code JScrollPane} 174 */ 175 public void syncWithScrollPane(JScrollPane sp) { 176 viewport = sp.getViewport(); 177 vsb = sp.getVerticalScrollBar(); 178 hsb = sp.getHorizontalScrollBar(); 179 rowHead = sp.getRowHeader(); 180 colHead = sp.getColumnHeader(); 181 lowerLeft = sp.getCorner(LOWER_LEFT_CORNER); 182 lowerRight = sp.getCorner(LOWER_RIGHT_CORNER); 183 upperLeft = sp.getCorner(UPPER_LEFT_CORNER); 184 upperRight = sp.getCorner(UPPER_RIGHT_CORNER); 185 vsbPolicy = sp.getVerticalScrollBarPolicy(); 186 hsbPolicy = sp.getHorizontalScrollBarPolicy(); 187 } 188 189 190 /** 191 * Removes an existing component. When a new component, such as 192 * the left corner, or vertical scrollbar, is added, the old one, 193 * if it exists, must be removed. 194 * <p> 195 * This method returns <code>newC</code>. If <code>oldC</code> is 196 * not equal to <code>newC</code> and is non-<code>null</code>, 197 * it will be removed from its parent. 198 * 199 * @param oldC the <code>Component</code> to replace 200 * @param newC the <code>Component</code> to add 201 * @return the <code>newC</code> 202 */ 203 protected Component addSingletonComponent(Component oldC, Component newC) 204 { 205 if ((oldC != null) && (oldC != newC)) { 206 oldC.getParent().remove(oldC); 207 } 208 return newC; 209 } 210 211 212 /** 213 * Adds the specified component to the layout. The layout is 214 * identified using one of: 215 * <ul> 216 * <li>ScrollPaneConstants.VIEWPORT 217 * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR 218 * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR 219 * <li>ScrollPaneConstants.ROW_HEADER 220 * <li>ScrollPaneConstants.COLUMN_HEADER 221 * <li>ScrollPaneConstants.LOWER_LEFT_CORNER 222 * <li>ScrollPaneConstants.LOWER_RIGHT_CORNER 223 * <li>ScrollPaneConstants.UPPER_LEFT_CORNER 224 * <li>ScrollPaneConstants.UPPER_RIGHT_CORNER 225 * </ul> 226 * 227 * @param s the component identifier 228 * @param c the component to be added 229 * @exception IllegalArgumentException if <code>s</code> is an invalid key 230 */ 231 public void addLayoutComponent(String s, Component c) 232 { 233 if (s.equals(VIEWPORT)) { 234 viewport = (JViewport)addSingletonComponent(viewport, c); 235 } 236 else if (s.equals(VERTICAL_SCROLLBAR)) { 237 vsb = (JScrollBar)addSingletonComponent(vsb, c); 238 } 239 else if (s.equals(HORIZONTAL_SCROLLBAR)) { 240 hsb = (JScrollBar)addSingletonComponent(hsb, c); 241 } 242 else if (s.equals(ROW_HEADER)) { 243 rowHead = (JViewport)addSingletonComponent(rowHead, c); 244 } 245 else if (s.equals(COLUMN_HEADER)) { 246 colHead = (JViewport)addSingletonComponent(colHead, c); 247 } 248 else if (s.equals(LOWER_LEFT_CORNER)) { 249 lowerLeft = addSingletonComponent(lowerLeft, c); 302 303 /** 304 * Returns the vertical scrollbar-display policy. 305 * 306 * @return an integer giving the display policy 307 * @see #setVerticalScrollBarPolicy 308 */ 309 public int getVerticalScrollBarPolicy() { 310 return vsbPolicy; 311 } 312 313 314 /** 315 * Sets the vertical scrollbar-display policy. The options 316 * are: 317 * <ul> 318 * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED 319 * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER 320 * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS 321 * </ul> 322 * Note: Applications should use the <code>JScrollPane</code> version 323 * of this method. It only exists for backwards compatibility 324 * with the Swing 1.0.2 (and earlier) versions of this class. 325 * 326 * @param x an integer giving the display policy 327 * @exception IllegalArgumentException if <code>x</code> is an invalid 328 * vertical scroll bar policy, as listed above 329 */ 330 public void setVerticalScrollBarPolicy(int x) { 331 switch (x) { 332 case VERTICAL_SCROLLBAR_AS_NEEDED: 333 case VERTICAL_SCROLLBAR_NEVER: 334 case VERTICAL_SCROLLBAR_ALWAYS: 335 vsbPolicy = x; 336 break; 337 default: 338 throw new IllegalArgumentException("invalid verticalScrollBarPolicy"); 339 } 340 } 341 342 343 /** 344 * Returns the horizontal scrollbar-display policy. 345 * 346 * @return an integer giving the display policy 347 * @see #setHorizontalScrollBarPolicy 348 */ 349 public int getHorizontalScrollBarPolicy() { 350 return hsbPolicy; 351 } 352 353 /** 354 * Sets the horizontal scrollbar-display policy. 355 * The options are:<ul> 356 * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED 357 * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER 358 * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS 359 * </ul> 360 * Note: Applications should use the <code>JScrollPane</code> version 361 * of this method. It only exists for backwards compatibility 362 * with the Swing 1.0.2 (and earlier) versions of this class. 363 * 364 * @param x an int giving the display policy 365 * @exception IllegalArgumentException if <code>x</code> is not a valid 366 * horizontal scrollbar policy, as listed above 367 */ 368 public void setHorizontalScrollBarPolicy(int x) { 369 switch (x) { 370 case HORIZONTAL_SCROLLBAR_AS_NEEDED: 371 case HORIZONTAL_SCROLLBAR_NEVER: 372 case HORIZONTAL_SCROLLBAR_ALWAYS: 373 hsbPolicy = x; 374 break; 375 default: 376 throw new IllegalArgumentException("invalid horizontalScrollBarPolicy"); 377 } 378 } 379 380 381 /** 382 * Returns the <code>JViewport</code> object that displays the 383 * scrollable contents. 384 * @return the <code>JViewport</code> object that displays the scrollable contents 385 * @see JScrollPane#getViewport 386 */ 387 public JViewport getViewport() { 388 return viewport; 389 } 390 391 392 /** 393 * Returns the <code>JScrollBar</code> object that handles horizontal scrolling. 394 * @return the <code>JScrollBar</code> object that handles horizontal scrolling 395 * @see JScrollPane#getHorizontalScrollBar 396 */ 397 public JScrollBar getHorizontalScrollBar() { 398 return hsb; 399 } 400 401 /** 402 * Returns the <code>JScrollBar</code> object that handles vertical scrolling. 403 * @return the <code>JScrollBar</code> object that handles vertical scrolling 404 * @see JScrollPane#getVerticalScrollBar 405 */ 406 public JScrollBar getVerticalScrollBar() { 407 return vsb; 408 } 409 410 411 /** 412 * Returns the <code>JViewport</code> object that is the row header. 413 * @return the <code>JViewport</code> object that is the row header 414 * @see JScrollPane#getRowHeader 415 */ 416 public JViewport getRowHeader() { 417 return rowHead; 418 } 419 420 421 /** 422 * Returns the <code>JViewport</code> object that is the column header. 423 * @return the <code>JViewport</code> object that is the column header 424 * @see JScrollPane#getColumnHeader 425 */ 426 public JViewport getColumnHeader() { 427 return colHead; 428 } 429 430 431 /** 432 * Returns the <code>Component</code> at the specified corner. 433 * @param key the <code>String</code> specifying the corner 434 * @return the <code>Component</code> at the specified corner, as defined in 435 * {@link ScrollPaneConstants}; if <code>key</code> is not one of the 436 * four corners, <code>null</code> is returned 437 * @see JScrollPane#getCorner 438 */ 439 public Component getCorner(String key) { 440 if (key.equals(LOWER_LEFT_CORNER)) { 441 return lowerLeft; 442 } 443 else if (key.equals(LOWER_RIGHT_CORNER)) { 444 return lowerRight; 445 } 446 else if (key.equals(UPPER_LEFT_CORNER)) { 447 return upperLeft; 448 } 449 else if (key.equals(UPPER_RIGHT_CORNER)) { 450 return upperRight; 451 } 452 else { 453 return null; 454 } 455 } 456 457 458 /** 459 * The preferred size of a <code>ScrollPane</code> is the size of the insets, 460 * plus the preferred size of the viewport, plus the preferred size of 461 * the visible headers, plus the preferred size of the scrollbars 462 * that will appear given the current view and the current 463 * scrollbar displayPolicies. 464 * <p>Note that the rowHeader is calculated as part of the preferred width 465 * and the colHeader is calculated as part of the preferred size. 466 * 467 * @param parent the <code>Container</code> that will be laid out 468 * @return a <code>Dimension</code> object specifying the preferred size of the 469 * viewport and any scrollbars 470 * @see ViewportLayout 471 * @see LayoutManager 472 */ 473 public Dimension preferredLayoutSize(Container parent) 474 { 475 /* Sync the (now obsolete) policy fields with the 476 * JScrollPane. 477 */ 478 JScrollPane scrollPane = (JScrollPane)parent; 479 vsbPolicy = scrollPane.getVerticalScrollBarPolicy(); 480 hsbPolicy = scrollPane.getHorizontalScrollBarPolicy(); 481 482 Insets insets = parent.getInsets(); 483 int prefWidth = insets.left + insets.right; 484 int prefHeight = insets.top + insets.bottom; 485 486 /* Note that viewport.getViewSize() is equivalent to 487 * viewport.getView().getPreferredSize() modulo a null 488 * view or a view whose size was explicitly set. 567 if ((hsb != null) && (hsbPolicy != HORIZONTAL_SCROLLBAR_NEVER)) { 568 if (hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) { 569 prefHeight += hsb.getPreferredSize().height; 570 } 571 else if ((viewSize != null) && (extentSize != null)) { 572 boolean canScroll = true; 573 if (view instanceof Scrollable) { 574 canScroll = !((Scrollable)view).getScrollableTracksViewportWidth(); 575 } 576 if (canScroll && (viewSize.width > extentSize.width)) { 577 prefHeight += hsb.getPreferredSize().height; 578 } 579 } 580 } 581 582 return new Dimension(prefWidth, prefHeight); 583 } 584 585 586 /** 587 * The minimum size of a <code>ScrollPane</code> is the size of the insets 588 * plus minimum size of the viewport, plus the scrollpane's 589 * viewportBorder insets, plus the minimum size 590 * of the visible headers, plus the minimum size of the 591 * scrollbars whose displayPolicy isn't NEVER. 592 * 593 * @param parent the <code>Container</code> that will be laid out 594 * @return a <code>Dimension</code> object specifying the minimum size 595 */ 596 public Dimension minimumLayoutSize(Container parent) 597 { 598 /* Sync the (now obsolete) policy fields with the 599 * JScrollPane. 600 */ 601 JScrollPane scrollPane = (JScrollPane)parent; 602 vsbPolicy = scrollPane.getVerticalScrollBarPolicy(); 603 hsbPolicy = scrollPane.getHorizontalScrollBarPolicy(); 604 605 Insets insets = parent.getInsets(); 606 int minWidth = insets.left + insets.right; 607 int minHeight = insets.top + insets.bottom; 608 609 /* If there's a viewport add its minimumSize. 610 */ 611 612 if (viewport != null) { 613 Dimension size = viewport.getMinimumSize(); 614 minWidth += size.width; 655 Dimension size = hsb.getMinimumSize(); 656 minWidth = Math.max(minWidth, size.width); 657 minHeight += size.height; 658 } 659 660 return new Dimension(minWidth, minHeight); 661 } 662 663 664 /** 665 * Lays out the scrollpane. The positioning of components depends on 666 * the following constraints: 667 * <ul> 668 * <li> The row header, if present and visible, gets its preferred 669 * width and the viewport's height. 670 * 671 * <li> The column header, if present and visible, gets its preferred 672 * height and the viewport's width. 673 * 674 * <li> If a vertical scrollbar is needed, i.e. if the viewport's extent 675 * height is smaller than its view height or if the <code>displayPolicy</code> 676 * is ALWAYS, it's treated like the row header with respect to its 677 * dimensions and is made visible. 678 * 679 * <li> If a horizontal scrollbar is needed, it is treated like the 680 * column header (see the paragraph above regarding the vertical scrollbar). 681 * 682 * <li> If the scrollpane has a non-<code>null</code> 683 * <code>viewportBorder</code>, then space is allocated for that. 684 * 685 * <li> The viewport gets the space available after accounting for 686 * the previous constraints. 687 * 688 * <li> The corner components, if provided, are aligned with the 689 * ends of the scrollbars and headers. If there is a vertical 690 * scrollbar, the right corners appear; if there is a horizontal 691 * scrollbar, the lower corners appear; a row header gets left 692 * corners, and a column header gets upper corners. 693 * </ul> 694 * 695 * @param parent the <code>Container</code> to lay out 696 */ 697 public void layoutContainer(Container parent) 698 { 699 /* Sync the (now obsolete) policy fields with the 700 * JScrollPane. 701 */ 702 JScrollPane scrollPane = (JScrollPane)parent; 703 vsbPolicy = scrollPane.getVerticalScrollBarPolicy(); 704 hsbPolicy = scrollPane.getHorizontalScrollBarPolicy(); 705 706 Rectangle availR = scrollPane.getBounds(); 707 availR.x = availR.y = 0; 708 709 Insets insets = parent.getInsets(); 710 availR.x = insets.left; 711 availR.y = insets.top; 712 availR.width -= insets.left + insets.right; 713 availR.height -= insets.top + insets.bottom; 714 715 /* Get the scrollPane's orientation. 1026 leftToRight ? vsbR.width : rowHeadR.width, 1027 hsbR.height); 1028 } 1029 1030 if (upperLeft != null) { 1031 upperLeft.setBounds(leftToRight ? rowHeadR.x : vsbR.x, 1032 colHeadR.y, 1033 leftToRight ? rowHeadR.width : vsbR.width, 1034 colHeadR.height); 1035 } 1036 1037 if (upperRight != null) { 1038 upperRight.setBounds(leftToRight ? vsbR.x : rowHeadR.x, 1039 colHeadR.y, 1040 leftToRight ? vsbR.width : rowHeadR.width, 1041 colHeadR.height); 1042 } 1043 } 1044 1045 /** 1046 * Adjusts the <code>Rectangle</code> <code>available</code> based on if 1047 * the vertical scrollbar is needed (<code>wantsVSB</code>). 1048 * The location of the vsb is updated in <code>vsbR</code>, and 1049 * the viewport border insets (<code>vpbInsets</code>) are used to offset 1050 * the vsb. This is only called when <code>wantsVSB</code> has 1051 * changed, eg you shouldn't invoke adjustForVSB(true) twice. 1052 */ 1053 private void adjustForVSB(boolean wantsVSB, Rectangle available, 1054 Rectangle vsbR, Insets vpbInsets, 1055 boolean leftToRight) { 1056 int oldWidth = vsbR.width; 1057 if (wantsVSB) { 1058 int vsbWidth = Math.max(0, Math.min(vsb.getPreferredSize().width, 1059 available.width)); 1060 1061 available.width -= vsbWidth; 1062 vsbR.width = vsbWidth; 1063 1064 if( leftToRight ) { 1065 vsbR.x = available.x + available.width + vpbInsets.right; 1066 } else { 1067 vsbR.x = available.x - vpbInsets.left; 1068 available.x += vsbWidth; 1069 } 1070 } 1071 else { 1072 available.width += oldWidth; 1073 } 1074 } 1075 1076 /** 1077 * Adjusts the <code>Rectangle</code> <code>available</code> based on if 1078 * the horizontal scrollbar is needed (<code>wantsHSB</code>). 1079 * The location of the hsb is updated in <code>hsbR</code>, and 1080 * the viewport border insets (<code>vpbInsets</code>) are used to offset 1081 * the hsb. This is only called when <code>wantsHSB</code> has 1082 * changed, eg you shouldn't invoked adjustForHSB(true) twice. 1083 */ 1084 private void adjustForHSB(boolean wantsHSB, Rectangle available, 1085 Rectangle hsbR, Insets vpbInsets) { 1086 int oldHeight = hsbR.height; 1087 if (wantsHSB) { 1088 int hsbHeight = Math.max(0, Math.min(available.height, 1089 hsb.getPreferredSize().height)); 1090 1091 available.height -= hsbHeight; 1092 hsbR.y = available.y + available.height + vpbInsets.bottom; 1093 hsbR.height = hsbHeight; 1094 } 1095 else { 1096 available.height += oldHeight; 1097 } 1098 } 1099 1100 1101 1102 /** 1103 * Returns the bounds of the border around the specified scroll pane's 1104 * viewport. 1105 * 1106 * @param scrollpane an instance of the {@code JScrollPane} 1107 * @return the size and position of the viewport border 1108 * @deprecated As of JDK version Swing1.1 1109 * replaced by <code>JScrollPane.getViewportBorderBounds()</code>. 1110 */ 1111 @Deprecated 1112 public Rectangle getViewportBorderBounds(JScrollPane scrollpane) { 1113 return scrollpane.getViewportBorderBounds(); 1114 } 1115 1116 /** 1117 * The UI resource version of <code>ScrollPaneLayout</code>. 1118 */ 1119 public static class UIResource extends ScrollPaneLayout implements javax.swing.plaf.UIResource {} 1120 } | 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 29 import javax.swing.border.*; 30 31 import java.awt.LayoutManager; 32 import java.awt.Component; 33 import java.awt.Container; 34 import java.awt.Rectangle; 35 import java.awt.Dimension; 36 import java.awt.Insets; 37 import java.io.Serializable; 38 39 40 /** 41 * The layout manager used by {@code JScrollPane}. 42 * {@code JScrollPaneLayout} is 43 * responsible for nine components: a viewport, two scrollbars, 44 * a row header, a column header, and four "corner" components. 45 * <p> 46 * <strong>Warning:</strong> 47 * Serialized objects of this class will not be compatible with 48 * future Swing releases. The current serialization support is 49 * appropriate for short term storage or RMI between applications running 50 * the same version of Swing. As of 1.4, support for long term storage 51 * of all JavaBeans™ 52 * has been added to the {@code java.beans} package. 53 * Please see {@link java.beans.XMLEncoder}. 54 * 55 * @see JScrollPane 56 * @see JViewport 57 * 58 * @author Hans Muller 59 * @since 1.2 60 */ 61 @SuppressWarnings("serial") // Same-version serialization only 62 public class ScrollPaneLayout 63 implements LayoutManager, ScrollPaneConstants, Serializable 64 { 65 66 /** 67 * The scrollpane's viewport child. 68 * Default is an empty {@code JViewport}. 69 * @see JScrollPane#setViewport 70 */ 71 protected JViewport viewport; 72 73 74 /** 75 * The scrollpane's vertical scrollbar child. 76 * Default is a {@code JScrollBar}. 77 * @see JScrollPane#setVerticalScrollBar 78 */ 79 protected JScrollBar vsb; 80 81 82 /** 83 * The scrollpane's horizontal scrollbar child. 84 * Default is a {@code JScrollBar}. 85 * @see JScrollPane#setHorizontalScrollBar 86 */ 87 protected JScrollBar hsb; 88 89 90 /** 91 * The row header child. Default is {@code null}. 92 * @see JScrollPane#setRowHeader 93 */ 94 protected JViewport rowHead; 95 96 97 /** 98 * The column header child. Default is {@code null}. 99 * @see JScrollPane#setColumnHeader 100 */ 101 protected JViewport colHead; 102 103 104 /** 105 * The component to display in the lower left corner. 106 * Default is {@code null}. 107 * @see JScrollPane#setCorner 108 */ 109 protected Component lowerLeft; 110 111 112 /** 113 * The component to display in the lower right corner. 114 * Default is {@code null}. 115 * @see JScrollPane#setCorner 116 */ 117 protected Component lowerRight; 118 119 120 /** 121 * The component to display in the upper left corner. 122 * Default is {@code null}. 123 * @see JScrollPane#setCorner 124 */ 125 protected Component upperLeft; 126 127 128 /** 129 * The component to display in the upper right corner. 130 * Default is {@code null}. 131 * @see JScrollPane#setCorner 132 */ 133 protected Component upperRight; 134 135 136 /** 137 * The display policy for the vertical scrollbar. 138 * The default is {@code ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED}. 139 * <p> 140 * This field is obsolete, please use the {@code JScrollPane} field instead. 141 * 142 * @see JScrollPane#setVerticalScrollBarPolicy 143 */ 144 protected int vsbPolicy = VERTICAL_SCROLLBAR_AS_NEEDED; 145 146 147 /** 148 * The display policy for the horizontal scrollbar. 149 * The default is {@code ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED}. 150 * <p> 151 * This field is obsolete, please use the {@code JScrollPane} field instead. 152 * 153 * @see JScrollPane#setHorizontalScrollBarPolicy 154 */ 155 protected int hsbPolicy = HORIZONTAL_SCROLLBAR_AS_NEEDED; 156 157 158 /** 159 * This method is invoked after the ScrollPaneLayout is set as the 160 * LayoutManager of a {@code JScrollPane}. 161 * It initializes all of the internal fields that 162 * are ordinarily set by {@code addLayoutComponent}. For example: 163 * <pre> 164 * ScrollPaneLayout mySPLayout = new ScrollPanelLayout() { 165 * public void layoutContainer(Container p) { 166 * super.layoutContainer(p); 167 * // do some extra work here ... 168 * } 169 * }; 170 * scrollpane.setLayout(mySPLayout): 171 * </pre> 172 * 173 * @param sp an instance of the {@code JScrollPane} 174 */ 175 public void syncWithScrollPane(JScrollPane sp) { 176 viewport = sp.getViewport(); 177 vsb = sp.getVerticalScrollBar(); 178 hsb = sp.getHorizontalScrollBar(); 179 rowHead = sp.getRowHeader(); 180 colHead = sp.getColumnHeader(); 181 lowerLeft = sp.getCorner(LOWER_LEFT_CORNER); 182 lowerRight = sp.getCorner(LOWER_RIGHT_CORNER); 183 upperLeft = sp.getCorner(UPPER_LEFT_CORNER); 184 upperRight = sp.getCorner(UPPER_RIGHT_CORNER); 185 vsbPolicy = sp.getVerticalScrollBarPolicy(); 186 hsbPolicy = sp.getHorizontalScrollBarPolicy(); 187 } 188 189 190 /** 191 * Removes an existing component. When a new component, such as 192 * the left corner, or vertical scrollbar, is added, the old one, 193 * if it exists, must be removed. 194 * <p> 195 * This method returns {@code newC}. If {@code oldC} is 196 * not equal to {@code newC} and is non-{@code null}, 197 * it will be removed from its parent. 198 * 199 * @param oldC the {@code Component} to replace 200 * @param newC the {@code Component} to add 201 * @return the {@code newC} 202 */ 203 protected Component addSingletonComponent(Component oldC, Component newC) 204 { 205 if ((oldC != null) && (oldC != newC)) { 206 oldC.getParent().remove(oldC); 207 } 208 return newC; 209 } 210 211 212 /** 213 * Adds the specified component to the layout. The layout is 214 * identified using one of: 215 * <ul> 216 * <li>ScrollPaneConstants.VIEWPORT 217 * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR 218 * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR 219 * <li>ScrollPaneConstants.ROW_HEADER 220 * <li>ScrollPaneConstants.COLUMN_HEADER 221 * <li>ScrollPaneConstants.LOWER_LEFT_CORNER 222 * <li>ScrollPaneConstants.LOWER_RIGHT_CORNER 223 * <li>ScrollPaneConstants.UPPER_LEFT_CORNER 224 * <li>ScrollPaneConstants.UPPER_RIGHT_CORNER 225 * </ul> 226 * 227 * @param s the component identifier 228 * @param c the component to be added 229 * @exception IllegalArgumentException if {@code s} is an invalid key 230 */ 231 public void addLayoutComponent(String s, Component c) 232 { 233 if (s.equals(VIEWPORT)) { 234 viewport = (JViewport)addSingletonComponent(viewport, c); 235 } 236 else if (s.equals(VERTICAL_SCROLLBAR)) { 237 vsb = (JScrollBar)addSingletonComponent(vsb, c); 238 } 239 else if (s.equals(HORIZONTAL_SCROLLBAR)) { 240 hsb = (JScrollBar)addSingletonComponent(hsb, c); 241 } 242 else if (s.equals(ROW_HEADER)) { 243 rowHead = (JViewport)addSingletonComponent(rowHead, c); 244 } 245 else if (s.equals(COLUMN_HEADER)) { 246 colHead = (JViewport)addSingletonComponent(colHead, c); 247 } 248 else if (s.equals(LOWER_LEFT_CORNER)) { 249 lowerLeft = addSingletonComponent(lowerLeft, c); 302 303 /** 304 * Returns the vertical scrollbar-display policy. 305 * 306 * @return an integer giving the display policy 307 * @see #setVerticalScrollBarPolicy 308 */ 309 public int getVerticalScrollBarPolicy() { 310 return vsbPolicy; 311 } 312 313 314 /** 315 * Sets the vertical scrollbar-display policy. The options 316 * are: 317 * <ul> 318 * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED 319 * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER 320 * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS 321 * </ul> 322 * Note: Applications should use the {@code JScrollPane} version 323 * of this method. It only exists for backwards compatibility 324 * with the Swing 1.0.2 (and earlier) versions of this class. 325 * 326 * @param x an integer giving the display policy 327 * @exception IllegalArgumentException if {@code x} is an invalid 328 * vertical scroll bar policy, as listed above 329 */ 330 public void setVerticalScrollBarPolicy(int x) { 331 switch (x) { 332 case VERTICAL_SCROLLBAR_AS_NEEDED: 333 case VERTICAL_SCROLLBAR_NEVER: 334 case VERTICAL_SCROLLBAR_ALWAYS: 335 vsbPolicy = x; 336 break; 337 default: 338 throw new IllegalArgumentException("invalid verticalScrollBarPolicy"); 339 } 340 } 341 342 343 /** 344 * Returns the horizontal scrollbar-display policy. 345 * 346 * @return an integer giving the display policy 347 * @see #setHorizontalScrollBarPolicy 348 */ 349 public int getHorizontalScrollBarPolicy() { 350 return hsbPolicy; 351 } 352 353 /** 354 * Sets the horizontal scrollbar-display policy. 355 * The options are:<ul> 356 * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED 357 * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER 358 * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS 359 * </ul> 360 * Note: Applications should use the {@code JScrollPane} version 361 * of this method. It only exists for backwards compatibility 362 * with the Swing 1.0.2 (and earlier) versions of this class. 363 * 364 * @param x an int giving the display policy 365 * @exception IllegalArgumentException if {@code x} is not a valid 366 * horizontal scrollbar policy, as listed above 367 */ 368 public void setHorizontalScrollBarPolicy(int x) { 369 switch (x) { 370 case HORIZONTAL_SCROLLBAR_AS_NEEDED: 371 case HORIZONTAL_SCROLLBAR_NEVER: 372 case HORIZONTAL_SCROLLBAR_ALWAYS: 373 hsbPolicy = x; 374 break; 375 default: 376 throw new IllegalArgumentException("invalid horizontalScrollBarPolicy"); 377 } 378 } 379 380 381 /** 382 * Returns the {@code JViewport} object that displays the 383 * scrollable contents. 384 * @return the {@code JViewport} object that displays the scrollable contents 385 * @see JScrollPane#getViewport 386 */ 387 public JViewport getViewport() { 388 return viewport; 389 } 390 391 392 /** 393 * Returns the {@code JScrollBar} object that handles horizontal scrolling. 394 * @return the {@code JScrollBar} object that handles horizontal scrolling 395 * @see JScrollPane#getHorizontalScrollBar 396 */ 397 public JScrollBar getHorizontalScrollBar() { 398 return hsb; 399 } 400 401 /** 402 * Returns the {@code JScrollBar} object that handles vertical scrolling. 403 * @return the {@code JScrollBar} object that handles vertical scrolling 404 * @see JScrollPane#getVerticalScrollBar 405 */ 406 public JScrollBar getVerticalScrollBar() { 407 return vsb; 408 } 409 410 411 /** 412 * Returns the {@code JViewport} object that is the row header. 413 * @return the {@code JViewport} object that is the row header 414 * @see JScrollPane#getRowHeader 415 */ 416 public JViewport getRowHeader() { 417 return rowHead; 418 } 419 420 421 /** 422 * Returns the {@code JViewport} object that is the column header. 423 * @return the {@code JViewport} object that is the column header 424 * @see JScrollPane#getColumnHeader 425 */ 426 public JViewport getColumnHeader() { 427 return colHead; 428 } 429 430 431 /** 432 * Returns the {@code Component} at the specified corner. 433 * @param key the {@code String} specifying the corner 434 * @return the {@code Component} at the specified corner, as defined in 435 * {@link ScrollPaneConstants}; if {@code key} is not one of the 436 * four corners, {@code null} is returned 437 * @see JScrollPane#getCorner 438 */ 439 public Component getCorner(String key) { 440 if (key.equals(LOWER_LEFT_CORNER)) { 441 return lowerLeft; 442 } 443 else if (key.equals(LOWER_RIGHT_CORNER)) { 444 return lowerRight; 445 } 446 else if (key.equals(UPPER_LEFT_CORNER)) { 447 return upperLeft; 448 } 449 else if (key.equals(UPPER_RIGHT_CORNER)) { 450 return upperRight; 451 } 452 else { 453 return null; 454 } 455 } 456 457 458 /** 459 * The preferred size of a {@code ScrollPane} is the size of the insets, 460 * plus the preferred size of the viewport, plus the preferred size of 461 * the visible headers, plus the preferred size of the scrollbars 462 * that will appear given the current view and the current 463 * scrollbar displayPolicies. 464 * <p>Note that the rowHeader is calculated as part of the preferred width 465 * and the colHeader is calculated as part of the preferred size. 466 * 467 * @param parent the {@code Container} that will be laid out 468 * @return a {@code Dimension} object specifying the preferred size of the 469 * viewport and any scrollbars 470 * @see ViewportLayout 471 * @see LayoutManager 472 */ 473 public Dimension preferredLayoutSize(Container parent) 474 { 475 /* Sync the (now obsolete) policy fields with the 476 * JScrollPane. 477 */ 478 JScrollPane scrollPane = (JScrollPane)parent; 479 vsbPolicy = scrollPane.getVerticalScrollBarPolicy(); 480 hsbPolicy = scrollPane.getHorizontalScrollBarPolicy(); 481 482 Insets insets = parent.getInsets(); 483 int prefWidth = insets.left + insets.right; 484 int prefHeight = insets.top + insets.bottom; 485 486 /* Note that viewport.getViewSize() is equivalent to 487 * viewport.getView().getPreferredSize() modulo a null 488 * view or a view whose size was explicitly set. 567 if ((hsb != null) && (hsbPolicy != HORIZONTAL_SCROLLBAR_NEVER)) { 568 if (hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) { 569 prefHeight += hsb.getPreferredSize().height; 570 } 571 else if ((viewSize != null) && (extentSize != null)) { 572 boolean canScroll = true; 573 if (view instanceof Scrollable) { 574 canScroll = !((Scrollable)view).getScrollableTracksViewportWidth(); 575 } 576 if (canScroll && (viewSize.width > extentSize.width)) { 577 prefHeight += hsb.getPreferredSize().height; 578 } 579 } 580 } 581 582 return new Dimension(prefWidth, prefHeight); 583 } 584 585 586 /** 587 * The minimum size of a {@code ScrollPane} is the size of the insets 588 * plus minimum size of the viewport, plus the scrollpane's 589 * viewportBorder insets, plus the minimum size 590 * of the visible headers, plus the minimum size of the 591 * scrollbars whose displayPolicy isn't NEVER. 592 * 593 * @param parent the {@code Container} that will be laid out 594 * @return a {@code Dimension} object specifying the minimum size 595 */ 596 public Dimension minimumLayoutSize(Container parent) 597 { 598 /* Sync the (now obsolete) policy fields with the 599 * JScrollPane. 600 */ 601 JScrollPane scrollPane = (JScrollPane)parent; 602 vsbPolicy = scrollPane.getVerticalScrollBarPolicy(); 603 hsbPolicy = scrollPane.getHorizontalScrollBarPolicy(); 604 605 Insets insets = parent.getInsets(); 606 int minWidth = insets.left + insets.right; 607 int minHeight = insets.top + insets.bottom; 608 609 /* If there's a viewport add its minimumSize. 610 */ 611 612 if (viewport != null) { 613 Dimension size = viewport.getMinimumSize(); 614 minWidth += size.width; 655 Dimension size = hsb.getMinimumSize(); 656 minWidth = Math.max(minWidth, size.width); 657 minHeight += size.height; 658 } 659 660 return new Dimension(minWidth, minHeight); 661 } 662 663 664 /** 665 * Lays out the scrollpane. The positioning of components depends on 666 * the following constraints: 667 * <ul> 668 * <li> The row header, if present and visible, gets its preferred 669 * width and the viewport's height. 670 * 671 * <li> The column header, if present and visible, gets its preferred 672 * height and the viewport's width. 673 * 674 * <li> If a vertical scrollbar is needed, i.e. if the viewport's extent 675 * height is smaller than its view height or if the {@code displayPolicy} 676 * is ALWAYS, it's treated like the row header with respect to its 677 * dimensions and is made visible. 678 * 679 * <li> If a horizontal scrollbar is needed, it is treated like the 680 * column header (see the paragraph above regarding the vertical scrollbar). 681 * 682 * <li> If the scrollpane has a non-{@code null} 683 * {@code viewportBorder}, then space is allocated for that. 684 * 685 * <li> The viewport gets the space available after accounting for 686 * the previous constraints. 687 * 688 * <li> The corner components, if provided, are aligned with the 689 * ends of the scrollbars and headers. If there is a vertical 690 * scrollbar, the right corners appear; if there is a horizontal 691 * scrollbar, the lower corners appear; a row header gets left 692 * corners, and a column header gets upper corners. 693 * </ul> 694 * 695 * @param parent the {@code Container} to lay out 696 */ 697 public void layoutContainer(Container parent) 698 { 699 /* Sync the (now obsolete) policy fields with the 700 * JScrollPane. 701 */ 702 JScrollPane scrollPane = (JScrollPane)parent; 703 vsbPolicy = scrollPane.getVerticalScrollBarPolicy(); 704 hsbPolicy = scrollPane.getHorizontalScrollBarPolicy(); 705 706 Rectangle availR = scrollPane.getBounds(); 707 availR.x = availR.y = 0; 708 709 Insets insets = parent.getInsets(); 710 availR.x = insets.left; 711 availR.y = insets.top; 712 availR.width -= insets.left + insets.right; 713 availR.height -= insets.top + insets.bottom; 714 715 /* Get the scrollPane's orientation. 1026 leftToRight ? vsbR.width : rowHeadR.width, 1027 hsbR.height); 1028 } 1029 1030 if (upperLeft != null) { 1031 upperLeft.setBounds(leftToRight ? rowHeadR.x : vsbR.x, 1032 colHeadR.y, 1033 leftToRight ? rowHeadR.width : vsbR.width, 1034 colHeadR.height); 1035 } 1036 1037 if (upperRight != null) { 1038 upperRight.setBounds(leftToRight ? vsbR.x : rowHeadR.x, 1039 colHeadR.y, 1040 leftToRight ? vsbR.width : rowHeadR.width, 1041 colHeadR.height); 1042 } 1043 } 1044 1045 /** 1046 * Adjusts the {@code Rectangle available} based on if 1047 * the vertical scrollbar is needed ({@code wantsVSB}). 1048 * The location of the vsb is updated in {@code vsbR}, and 1049 * the viewport border insets ({@code vpbInsets}) are used to offset 1050 * the vsb. This is only called when {@code wantsVSB} has 1051 * changed, eg you shouldn't invoke adjustForVSB(true) twice. 1052 */ 1053 private void adjustForVSB(boolean wantsVSB, Rectangle available, 1054 Rectangle vsbR, Insets vpbInsets, 1055 boolean leftToRight) { 1056 int oldWidth = vsbR.width; 1057 if (wantsVSB) { 1058 int vsbWidth = Math.max(0, Math.min(vsb.getPreferredSize().width, 1059 available.width)); 1060 1061 available.width -= vsbWidth; 1062 vsbR.width = vsbWidth; 1063 1064 if( leftToRight ) { 1065 vsbR.x = available.x + available.width + vpbInsets.right; 1066 } else { 1067 vsbR.x = available.x - vpbInsets.left; 1068 available.x += vsbWidth; 1069 } 1070 } 1071 else { 1072 available.width += oldWidth; 1073 } 1074 } 1075 1076 /** 1077 * Adjusts the {@code Rectangle available} based on if 1078 * the horizontal scrollbar is needed ({@code wantsHSB}). 1079 * The location of the hsb is updated in {@code hsbR}, and 1080 * the viewport border insets ({@code vpbInsets}) are used to offset 1081 * the hsb. This is only called when {@code wantsHSB} has 1082 * changed, eg you shouldn't invoked adjustForHSB(true) twice. 1083 */ 1084 private void adjustForHSB(boolean wantsHSB, Rectangle available, 1085 Rectangle hsbR, Insets vpbInsets) { 1086 int oldHeight = hsbR.height; 1087 if (wantsHSB) { 1088 int hsbHeight = Math.max(0, Math.min(available.height, 1089 hsb.getPreferredSize().height)); 1090 1091 available.height -= hsbHeight; 1092 hsbR.y = available.y + available.height + vpbInsets.bottom; 1093 hsbR.height = hsbHeight; 1094 } 1095 else { 1096 available.height += oldHeight; 1097 } 1098 } 1099 1100 1101 1102 /** 1103 * Returns the bounds of the border around the specified scroll pane's 1104 * viewport. 1105 * 1106 * @param scrollpane an instance of the {@code JScrollPane} 1107 * @return the size and position of the viewport border 1108 * @deprecated As of JDK version Swing1.1 1109 * replaced by {@code JScrollPane.getViewportBorderBounds()}. 1110 */ 1111 @Deprecated 1112 public Rectangle getViewportBorderBounds(JScrollPane scrollpane) { 1113 return scrollpane.getViewportBorderBounds(); 1114 } 1115 1116 /** 1117 * The UI resource version of {@code ScrollPaneLayout}. 1118 */ 1119 public static class UIResource extends ScrollPaneLayout implements javax.swing.plaf.UIResource {} 1120 } |