Source for javax.swing.ScrollPaneLayout

   1: /* ScrollPaneLayout.java --
   2:    Copyright (C) 2002, 2004  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing;
  40: 
  41: import java.awt.Component;
  42: import java.awt.Container;
  43: import java.awt.Dimension;
  44: import java.awt.Insets;
  45: import java.awt.LayoutManager;
  46: import java.awt.Rectangle;
  47: import java.io.Serializable;
  48: 
  49: /**
  50:  * ScrollPaneLayout
  51:  * @author    Andrew Selkirk
  52:  * @version    1.0
  53:  */
  54: public class ScrollPaneLayout
  55:   implements LayoutManager, ScrollPaneConstants, Serializable
  56: {
  57:   private static final long serialVersionUID = -4480022884523193743L;
  58: 
  59:   public static class UIResource extends ScrollPaneLayout 
  60:     implements javax.swing.plaf.UIResource
  61:   {
  62:     public UIResource()
  63:     {
  64:       super();
  65:     }
  66:   }
  67: 
  68:   protected JViewport viewport;
  69:   protected JScrollBar vsb;
  70:   protected JScrollBar hsb;
  71:   protected JViewport rowHead;
  72:   protected JViewport colHead;
  73:   protected Component lowerLeft;
  74:   protected Component lowerRight;
  75:   protected Component upperLeft;
  76:   protected Component upperRight;
  77:   protected int vsbPolicy;
  78:   protected int hsbPolicy;
  79: 
  80:   public ScrollPaneLayout()
  81:   {
  82:     // Nothing to do here.
  83:   }
  84: 
  85:   public void syncWithScrollPane(JScrollPane scrollPane) 
  86:   {
  87:     viewport = scrollPane.getViewport();
  88:     rowHead = scrollPane.getRowHeader();
  89:     colHead = scrollPane.getColumnHeader();
  90:     vsb = scrollPane.getVerticalScrollBar();
  91:     hsb = scrollPane.getHorizontalScrollBar();
  92:     vsbPolicy = scrollPane.getVerticalScrollBarPolicy();
  93:     hsbPolicy = scrollPane.getHorizontalScrollBarPolicy();
  94:     lowerLeft = scrollPane.getCorner(LOWER_LEFT_CORNER);
  95:     lowerRight = scrollPane.getCorner(LOWER_RIGHT_CORNER);
  96:     upperLeft = scrollPane.getCorner(UPPER_LEFT_CORNER);
  97:     upperRight = scrollPane.getCorner(UPPER_RIGHT_CORNER);    
  98:   }
  99: 
 100:   /**
 101:    * Removes an existing component.  If oldComponent is not null
 102:    * and is not equal to newComponent, oldComponent must be removed
 103:    * from its parent.
 104:    * @param oldComponent the old Component that may need to be removed.
 105:    * @param newComponent the Component to add.
 106:    * @return the newComponent
 107:    */
 108:   protected Component addSingletonComponent(Component oldComponent,
 109:                                             Component newComponent) 
 110:   {
 111:     if (oldComponent != null && oldComponent != newComponent)
 112:       oldComponent.getParent().remove(oldComponent);
 113:     return newComponent;
 114:   }
 115: 
 116:   /**
 117:    * Add the specified component to the layout. 
 118:    * @param key must be one of VIEWPORT, VERTICAL_SCROLLBAR,
 119:    * HORIZONTAL_SCROLLBAR, ROW_HEADER, COLUMN_HEADER,
 120:    * LOWER_RIGHT_CORNER, LOWER_LEFT_CORNER, UPPER_RIGHT_CORNER,
 121:    * UPPER_LEFT_CORNER.
 122:    * @param component the Component to add
 123:    * @throws IllegalArgumentException if key is not as above
 124:    */
 125:   public void addLayoutComponent(String key, Component component) 
 126:   {
 127:     if (key == VIEWPORT)
 128:       viewport = (JViewport) component;
 129:     else if (key == VERTICAL_SCROLLBAR)
 130:       vsb = (JScrollBar) component;
 131:     else if (key == HORIZONTAL_SCROLLBAR)
 132:       hsb = (JScrollBar) component;
 133:     else if (key == ROW_HEADER)
 134:       rowHead = (JViewport) component;
 135:     else if (key == COLUMN_HEADER)
 136:       colHead = (JViewport) component;
 137:     else if (key == LOWER_RIGHT_CORNER)
 138:       lowerRight = component;
 139:     else if (key == UPPER_RIGHT_CORNER)
 140:       upperRight = component;
 141:     else if (key == LOWER_LEFT_CORNER)
 142:       lowerLeft = component;
 143:     else if (key == UPPER_LEFT_CORNER)
 144:       upperLeft = component;
 145:     else
 146:       throw new IllegalArgumentException();
 147:   }
 148: 
 149:   public void removeLayoutComponent(Component component) 
 150:   {
 151:     if (component == viewport)
 152:       viewport = null;
 153:     else if (component == vsb)
 154:       vsb = null;
 155:     else if (component == hsb)
 156:       hsb = null;
 157:     else if (component == rowHead)
 158:       rowHead = null;
 159:     else if (component == colHead)
 160:       colHead = null;
 161:     else if (component == lowerRight)
 162:       lowerRight = null;
 163:     else if (component == upperRight)
 164:       upperRight = null;
 165:     else if (component == lowerLeft)
 166:       lowerLeft = null;
 167:     else if (component == upperLeft)
 168:       upperLeft = null;
 169:   }
 170: 
 171:   public int getVerticalScrollBarPolicy()
 172:   {
 173:     return vsbPolicy;
 174:   }
 175:   
 176:   /**
 177:    * Sets the vertical scrollbar policy.
 178:    * @param policy must be one of VERTICAL_SCROLLBAR_AS_NEEDED,
 179:    * VERTICAL_SCROLLBAR_NEVER, VERTICAL_SCROLLBAR_ALWAYS.
 180:    * @throws IllegalArgumentException if policy is not one of the valid
 181:    * JScrollBar policies.
 182:    */
 183:   public void setVerticalScrollBarPolicy(int policy)
 184:   {
 185:     if (policy != VERTICAL_SCROLLBAR_AS_NEEDED && 
 186:         policy != VERTICAL_SCROLLBAR_NEVER &&
 187:         policy != VERTICAL_SCROLLBAR_ALWAYS)
 188:       throw new IllegalArgumentException("Illegal Scrollbar Policy");
 189:     vsbPolicy = policy;
 190:   }
 191: 
 192:   public int getHorizontalScrollBarPolicy()
 193:   {
 194:     return hsbPolicy;
 195:   }
 196: 
 197:   /**
 198:    * Sets the horizontal scrollbar policy.
 199:    * @param policy must be one of HORIZONTAL_SCROLLBAR_AS_NEEDED,
 200:    * HORIZONTAL_SCROLLBAR_NEVER, HORIZONTAL_SCROLLBAR_ALWAYS.
 201:    * @throws IllegalArgumentException if policy is not one of the valid 
 202:    * JScrollbar policies.
 203:    */
 204:   public void setHorizontalScrollBarPolicy(int policy)
 205:   {
 206:     if (policy != HORIZONTAL_SCROLLBAR_AS_NEEDED && 
 207:         policy != HORIZONTAL_SCROLLBAR_NEVER &&
 208:         policy != HORIZONTAL_SCROLLBAR_ALWAYS)
 209:       throw new IllegalArgumentException("Illegal Scrollbar Policy");
 210:     hsbPolicy = policy;
 211:   }
 212: 
 213:   public JViewport getViewport()
 214:   {
 215:     return viewport;
 216:   }
 217: 
 218:   public JScrollBar getHorizontalScrollBar()
 219:   {
 220:     return hsb;
 221:   }
 222: 
 223:   public JScrollBar getVerticalScrollBar()
 224:   {
 225:     return vsb;
 226:   }
 227: 
 228:   public JViewport getRowHeader()
 229:   {
 230:     return rowHead;
 231:   }
 232: 
 233:   public JViewport getColumnHeader()
 234:   {
 235:     return colHead;
 236:   }
 237: 
 238:   /**
 239:    * Returns the Component at the specified corner.
 240:    * @param key the corner.
 241:    * @return the Component at the specified corner, or null if
 242:    * key is not one of the four valid corners.
 243:    */
 244:   public Component getCorner(String key)
 245:   {
 246:     if (key == LOWER_RIGHT_CORNER)
 247:       return lowerRight;
 248:     else if (key == UPPER_RIGHT_CORNER)
 249:       return upperRight;
 250:     else if (key == LOWER_LEFT_CORNER)
 251:       return lowerLeft;
 252:     else if (key == UPPER_LEFT_CORNER)
 253:       return upperLeft;
 254:     return null;
 255:   }
 256: 
 257:   public Dimension preferredLayoutSize(Container parent) 
 258:   {
 259:     // Sun's implementation simply throws a ClassCastException if
 260:     // parent is no JScrollPane, so do we.
 261:     JScrollPane sc = (JScrollPane) parent;
 262:     Dimension viewportSize = viewport.getPreferredSize();
 263:     Dimension viewSize = viewport.getViewSize();
 264:     int width = viewportSize.width;
 265:     int height = viewportSize.height;
 266: 
 267:     // horizontal scrollbar needed if the view's preferred width
 268:     // is larger than the viewport's preferred width
 269:     if (hsb != null && viewSize.width > viewportSize.width)
 270:       height += hsb.getPreferredSize().height;
 271: 
 272:     // vertical scrollbar needed if the view's preferred height
 273:     // is larger than the viewport's preferred height
 274:     if (vsb != null && viewSize.height > viewportSize.height)
 275:       width += vsb.getPreferredSize().width;
 276:     if (rowHead != null && rowHead.isVisible())
 277:       width += rowHead.getPreferredSize().width;
 278:     if (colHead != null && colHead.isVisible())
 279:       height += colHead.getPreferredSize().height;
 280:     Insets i = sc.getInsets();
 281:     return new Dimension(width + i.left + i.right,
 282:                          height + i.left + i.right);
 283:   }
 284: 
 285:   public Dimension minimumLayoutSize(Container parent)
 286:   {
 287:     // Sun's implementation simply throws a ClassCastException if
 288:     // parent is no JScrollPane, so do we.
 289:     JScrollPane sc = (JScrollPane) parent;
 290:     Insets i = sc.getInsets();
 291:     Dimension viewportMinSize = sc.getViewport().getMinimumSize();
 292: 
 293:     int width = i.left + i.right + viewportMinSize.width;
 294:     if (sc.getVerticalScrollBarPolicy()
 295:         != JScrollPane.VERTICAL_SCROLLBAR_NEVER)
 296:       width += sc.getVerticalScrollBar().getMinimumSize().width;
 297: 
 298:     int height = i.top + i.bottom + viewportMinSize.height;
 299:     if (sc.getHorizontalScrollBarPolicy()
 300:         != JScrollPane.HORIZONTAL_SCROLLBAR_NEVER)
 301:       height += sc.getHorizontalScrollBar().getMinimumSize().height;
 302: 
 303:     return new Dimension(width, height);
 304:   }
 305: 
 306:   /**
 307:    *
 308:    *     +----+--------------------+----+ y1
 309:    *     | c1 |   column header    | c2 |
 310:    *     +----+--------------------+----+ y2
 311:    *     | r  |                    | v  |
 312:    *     | o  |                    |    |
 313:    *     | w  |                    | s  |
 314:    *     |    |                    | r  |
 315:    *     | h  |                    | o  |
 316:    *     | e  |      viewport      | l  |
 317:    *     | a  |                    | l  |
 318:    *     | d  |                    | b  |
 319:    *     | e  |                    | a  |
 320:    *     | r  |                    | r  |
 321:    *     +----+--------------------+----+ y3
 322:    *     | c3 |    h scrollbar     | c4 |
 323:    *     +----+--------------------+----+ y4
 324:    *    x1   x2                   x3   x4
 325:    *   
 326:    */
 327:   public void layoutContainer(Container parent)
 328:   {
 329:     // Sun's implementation simply throws a ClassCastException if
 330:     // parent is no JScrollPane, so do we.
 331:     JScrollPane sc = (JScrollPane) parent;
 332:     JViewport viewport = sc.getViewport();
 333:     Component view = viewport.getView();
 334:     
 335:     // If there is no view in the viewport, there is no work to be done.
 336:     if (view == null)
 337:       return;
 338:     
 339:     Dimension viewSize = viewport.getView().getPreferredSize();
 340: 
 341:     int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
 342:     int y1 = 0, y2 = 0, y3 = 0, y4 = 0;
 343:     Rectangle scrollPaneBounds = SwingUtilities.calculateInnerArea(sc, null);
 344: 
 345:     x1 = scrollPaneBounds.x;
 346:     y1 = scrollPaneBounds.y;
 347:     x4 = scrollPaneBounds.x + scrollPaneBounds.width;
 348:     y4 = scrollPaneBounds.y + scrollPaneBounds.height;
 349:     if (colHead != null)
 350:       y2 = y1 + colHead.getPreferredSize().height;
 351:     else
 352:       y2 = y1;
 353: 
 354:     if (rowHead != null)
 355:       x2 = x1 + rowHead.getPreferredSize().width;
 356:     else
 357:       x2 = x1;
 358: 
 359:     int vsbPolicy = sc.getVerticalScrollBarPolicy();
 360:     int hsbPolicy = sc.getHorizontalScrollBarPolicy();
 361:     
 362:     int vsWidth = 0;
 363:     int hsHeight = 0;
 364: 
 365:     boolean showVsb = 
 366:       (vsb != null)
 367:       && ((vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS)
 368:           || (vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED 
 369:               && viewSize.height > (y4 - y2)));
 370:     
 371:     if (showVsb)
 372:       vsWidth = vsb.getPreferredSize().width;
 373:     
 374:     // The horizontal scroll bar may become necessary if the vertical scroll
 375:     // bar appears, reducing the space, left for the component.
 376:     
 377:     boolean showHsb = 
 378:       (hsb != null)
 379:       && ((hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS)
 380:           || (hsbPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED 
 381:               && viewSize.width > (x4 - x2 - vsWidth)));
 382:     
 383:     if (showHsb)
 384:       hsHeight = hsb.getPreferredSize().height;
 385:     
 386:     // If the horizontal scroll bar appears, and the vertical scroll bar
 387:     // was not necessary assuming that there is no horizontal scroll bar,
 388:     // the vertical scroll bar may become necessary because the horizontal
 389:     // scroll bar reduces the vertical space for the component.
 390:     if (!showVsb)
 391:       {
 392:         showVsb = 
 393:           (vsb != null)
 394:           && ((vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS)
 395:               || (vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED 
 396:                   && viewSize.height > (y4 - y2)));
 397:     
 398:         if (showVsb)
 399:           vsWidth = vsb.getPreferredSize().width;
 400:       }
 401: 
 402:     x3 = x4 - vsWidth;
 403:     y3 = y4 - hsHeight;
 404: 
 405:     // now set the layout
 406:     if (viewport != null)
 407:       viewport.setBounds(new Rectangle(x2, y2, x3 - x2, y3 - y2));
 408: 
 409:     if (colHead != null)
 410:       colHead.setBounds(new Rectangle(x2, y1, x3 - x2, y2 - y1));
 411: 
 412:     if (rowHead != null)
 413:       rowHead.setBounds(new Rectangle(x1, y2, x2 - x1, y3 - y2));
 414: 
 415:     if (showVsb)
 416:       {
 417:         vsb.setVisible(true);
 418:         vsb.setBounds(new Rectangle(x3, y2, x4 - x3, y3 - y2));
 419:       }
 420:     else if (vsb != null)
 421:       vsb.setVisible(false);
 422: 
 423:     if (showHsb)
 424:       {
 425:         hsb.setVisible(true);
 426:         hsb.setBounds(new Rectangle(x2, y3, x3 - x2, y4 - y3));
 427:       }
 428:     else if (hsb != null)
 429:       hsb.setVisible(false);
 430: 
 431:     if (upperLeft != null)
 432:       upperLeft.setBounds(new Rectangle(x1, y1, x2 - x1, y2 - y1));
 433: 
 434:     if (upperRight != null)
 435:       upperRight.setBounds(new Rectangle(x3, y1, x4 - x3, y2 - y1));
 436: 
 437:     if (lowerLeft != null)
 438:       lowerLeft.setBounds(new Rectangle(x1, y3, x2 - x1, y4 - y3));
 439: 
 440:     if (lowerRight != null)
 441:       lowerRight.setBounds(new Rectangle(x3, y3, x4 - x3, y4 - y3));
 442:   }
 443: 
 444:   /**
 445:    * Returns the bounds of the border around a ScrollPane's viewport.
 446:    *
 447:    * @param scrollPane the ScrollPane for which's viewport the border
 448:    *     is requested
 449:    *
 450:    * @deprecated As of Swing 1.1 replaced by
 451:    *     {@link javax.swing.JScrollPane#getViewportBorderBounds}.
 452:    */
 453:   public Rectangle getViewportBorderBounds(JScrollPane scrollPane) 
 454:   {
 455:     return null;
 456:   }
 457: 
 458: 
 459: }