Source for javax.swing.ViewportLayout

   1: /* ViewportLayout.java --
   2:    Copyright (C) 2002, 2004, 2006 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: package javax.swing;
  39: 
  40: import java.awt.Component;
  41: import java.awt.Container;
  42: import java.awt.Dimension;
  43: import java.awt.LayoutManager;
  44: import java.awt.Point;
  45: import java.awt.Rectangle;
  46: import java.io.Serializable;
  47: 
  48: /**
  49:  * The default layout for {@link JViewport}. The viewport makes its view the
  50:  * same size as itself, but not smaller than its minimum size.
  51:  *
  52:  * If the port extends extends into space <em>past</em> the edge of the view,
  53:  * this layout manager moves the port up or to the left, in view space, by the
  54:  * amount of empty space (keep the lower and right edges lined up).
  55:  *
  56:  * @author  Andrew Selkirk
  57:  * @author  Graydon Hoare
  58:  * @author  Audrius Meskauskas (audriusa@Bioinformatics.org)
  59:  */
  60: public class ViewportLayout implements LayoutManager, Serializable
  61: {
  62:   private static final long serialVersionUID = -788225906076097229L;
  63: 
  64:   public ViewportLayout()
  65:   {
  66:     // Nothing to do here.
  67:   }
  68: 
  69:   /**
  70:    * The method is not used with this manager.
  71:    */
  72:   public void addLayoutComponent(String name, Component c)
  73:   {
  74:     // Nothing to do here.
  75:   }
  76: 
  77:   /**
  78:    * The method is not used with this manager.
  79:    */
  80:   public void removeLayoutComponent(Component c)
  81:   {
  82:     // Nothing to do here.
  83:   }
  84: 
  85:   /**
  86:    * Get the preferred layout size. If the view implements
  87:    * {@link Scrollable}, this method returns
  88:    * {@link Scrollable#getPreferredScrollableViewportSize}.
  89:    * Otherwise, it returns {@link Component#getPreferredSize()}.
  90:    *
  91:    * @return the preferred layout size, as described about.
  92:    */
  93:   public Dimension preferredLayoutSize(Container parent)
  94:   {
  95:     JViewport vp = (JViewport)parent;
  96:     Component view = vp.getView();
  97:     if (view != null)
  98:       {
  99:         if (view instanceof Scrollable)
 100:           return ((Scrollable)view).getPreferredScrollableViewportSize();
 101:         return view.getPreferredSize();
 102:       }
 103:     else
 104:       return new Dimension();
 105:   }
 106: 
 107:   /**
 108:    * Get the minimum layout size. Normally this method returns the value,
 109:    * returned by the view method {@link Component#getMinimumSize()}.
 110:    *
 111:    * If the view is not set, the zero size is returned.
 112:    *
 113:    * @param parent the viewport
 114:    * @return the minimum layout size.
 115:    */
 116:   public Dimension minimumLayoutSize(Container parent)
 117:   {
 118:     // These values have been determined by the Mauve test for this method.
 119:     return new Dimension(4, 4);
 120:   }
 121: 
 122:   /**
 123:    * Layout the view and viewport to respect the following rules. These are not
 124:    * precisely the rules described in sun's javadocs, but they are the rules
 125:    * which sun's swing implementation follows, if you watch its behavior:
 126:    * <ol>
 127:    * <li>If the port is smaller than the view, leave the view at its current
 128:    * size.</li>
 129:    * <li>If the view is smaller than the port, the view is top aligned.</li>
 130:    * <li>If the view tracks the port size, the view position is always zero and
 131:    * the size equal to the viewport size</li>
 132:    * <li>In {@link JViewport#setViewSize(Dimension)}, the view size is never
 133:    * set smaller that its minimum size.</li>
 134:    * </ol>
 135:    *
 136:    * @see JViewport#getViewSize
 137:    * @see JViewport#setViewSize
 138:    * @see JViewport#getViewPosition
 139:    * @see JViewport#setViewPosition
 140:    */
 141:   public void layoutContainer(Container parent)
 142:   {
 143:     // The way to interpret this function is basically to ignore the names
 144:     // of methods it calls, and focus on the variable names here. getViewRect
 145:     // doesn't, for example, return the view; it returns the port bounds in
 146:     // view space. Likwise setViewPosition doesn't reposition the view; it
 147:     // positions the port, in view coordinates.
 148: 
 149:     JViewport port = (JViewport) parent;
 150:     Component view = port.getView();
 151: 
 152:     if (view == null)
 153:       return;
 154: 
 155:     // These dimensions and positions are in *view space*. Do not mix
 156:     // variables in here from port space (eg. parent.getBounds()). This
 157:     // function should be entirely in view space, because the methods on
 158:     // the viewport require inputs in view space.
 159: 
 160:     Rectangle portBounds = port.getViewRect();
 161:     Dimension viewPref = new Dimension(view.getPreferredSize());
 162: 
 163:     Point portLowerRight = new Point(portBounds.x + portBounds.width,
 164:                                      portBounds.y + portBounds.height);
 165: 
 166:     // vertical implementation of the above rules
 167:     if (view instanceof Scrollable)
 168:       {
 169:         Scrollable sView = (Scrollable) view;
 170: 
 171:         // If the view size matches viewport size, the port offset can
 172:         // only be zero.
 173:         if (sView.getScrollableTracksViewportWidth())
 174:           {
 175:             viewPref.width = portBounds.width;
 176:             portBounds.x = 0;
 177:           }
 178:         if (sView.getScrollableTracksViewportHeight())
 179:           {
 180:             viewPref.height = portBounds.height;
 181:             portBounds.y = 0;
 182:           }
 183:       }
 184: 
 185:      if (viewPref.width < portBounds.width)
 186:        viewPref.width = portBounds.width;
 187:      if (viewPref.height < portBounds.height)
 188:        viewPref.height = portBounds.height;
 189: 
 190:     // If the view is larger than the port, the port is top and right
 191:     // aligned.
 192:     if (portLowerRight.x > viewPref.width)
 193:       portBounds.x = 0;
 194: 
 195:     if (portLowerRight.y > viewPref.height)
 196:       portBounds.y = 0;
 197: 
 198:     port.setViewSize(viewPref);
 199:     port.setViewPosition(portBounds.getLocation());
 200:   }
 201: 
 202: }