Swing JFC Java

import java.awt.*;
import java.util.LinkedList;
import java.io.Serializable;
/*
 * Relative Component Layout Manager
 * Copyright (c) 1999 John Catherino
 * The cajo project: https://cajo.dev.java.net
 *
 * For issues or suggestions mailto:cajo@dev.java.net
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License, at version
 * 2.1 of the licence, or any later version published by the Free Software
 * Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You can receive a copy of the GNU Lesser General Public License from their
 * website, http://fsf.org/licenses/lgpl.html; or via snail mail, Free
 * Software Foundation Inc., 51 Franklin Street, Boston MA 02111-1301, USA
 */
/**
 * A rather unique LayoutManager. In addition to laying out components relative
 * to the container, it also supports layout relative to components within
 * the container. Its purpose is to support arbitrarily complex component
 * layouts, of an unlimited number of components, within a single container. It
 * can easily create complex layouts that would otherwise require many
 * subpanels, and multiple standard layout managers. It also can create layouts
 * that are completely impossible, with standard layout managers. These
 * features make this layout manager extremely flexible, and makes
 * advancedlayouts extremely fast. It just may be, the last and only
 * LayoutManager you'll ever need.
 * 


 * 
 * Components can be laid out above, below, left, or right of either a
 * referenced component in the panel, or to the panel itself. Its width and
 * height can be specified with similar flexibility. Absolute and proportional
 * bounds are also supported. In typical use, one or more 'reference'
 * tiles are laid, and the rest of the components are set relative to them.
 * 


 * 
 * Usage example:


 * panel.add(new JLabel("Label text:"), new Object[]{
 *       new Integer(TileLayout.LEFTINDENT + TileLayout.NOOFFSET +
 *       TileLayout.PROPWIDTH + TileLayout.FULLHEIGHT), refComponent,
 *       new Insets(-5, 10, 5, 10), new Rectangle(0, 0, 333, 0)
 * // proportion rectangle 33.3%w
 *       });
 * 

 * 
 * 

 * 


 * 
 * Up to four alignment constraints can be specified, their order does not
 * matter:
 * 
 * 


 * 


     * 
  •  Positioning constants for indent, offset, width, and height
     * 
  •  A Component for placement relative to, otherwise the container
     * 
  •  A Rectangle for fixed and proportional component bounds
     * 
  •  Insets to trim the resulting component boundaries
     * 

 * 


 * 
 * Note: since the JRE draws components from last added
 * to first; the manager lays them out similarly. Therefore, in order to layout
 * relative to another component, the reference component must be added after
 * the dependent one. I know this can be a drag at first, but it becomes
 * critically important when components are laid out on top of others, or
 * overlapping. This is a super cool capability of this layout manager.
 * 
 * @version 1.0, 01-Nov-99 Initial release
 * @author John Catherino
 */
public final class TileLayout implements LayoutManager2, Serializable {
   private static final long serialVersionUID = 1L;
   private static final Dimension NONE  = new Dimension();
   private final LinkedList components  = new LinkedList();
   private final LinkedList constraints = new LinkedList();
   private void align(Dimension cont, Object cons[], Component comp) {
      int align = 0;
      Insets insets = null;
      Rectangle tile = null, fixd = null;
      if (cons != null) {
         for (int i = 0; i < cons.length; i++) { // gather constraints
            if (cons[i] != null) {
               if (cons[i] instanceof Rectangle) fixd = (Rectangle)cons[i];
               else if (cons[i] instanceof Insets) insets = (Insets)cons[i];
               else if (cons[i] instanceof Integer) align = ((Integer)cons[i]).intValue();
               else if (cons[i] instanceof Component) tile = ((Component)cons[i]).getBounds();
            }
         }
      }
      if (tile == null) tile = new Rectangle(cont);
      Rectangle pref = new Rectangle(tile.getLocation(), comp.getPreferredSize());
      // perform component positioning:
      if ((align & 0x004000) != 0) pref.width = fixd.width;
      else if ((align & 0x008000) != 0) pref.width = (tile.width * fixd.width + 500) / 1000;
      else if ((align & 0x010000) != 0) pref.width = tile.width;
      if ((align & 0x080000) != 0) pref.height = fixd.height;
      else if ((align & 0x100000) != 0) pref.height = (tile.height
            * fixd.height + 500) / 1000;
      else if ((align & 0x200000) != 0) pref.height = tile.height;
      if ((align & 0x000001) != 0) pref.x -= pref.width;
      else if ((align & 0x000002) != 0) pref.x += (tile.width - pref.width >> 1);
      else if ((align & 0x000004) != 0) pref.x += tile.width - pref.width;
      else if ((align & 0x000008) != 0) pref.x += tile.width;
      else if ((align & 0x000010) != 0) pref.x += fixd.x;
      else if ((align & 0x000020) != 0) pref.x += (tile.width * fixd.x + 500) / 1000;
      if ((align & 0x000040) != 0) pref.y -= pref.height;
      else if ((align & 0x000080) != 0) pref.y += (tile.height - pref.height >> 1);
      else if ((align & 0x000100) != 0) pref.y += tile.height - pref.height;
      else if ((align & 0x000200) != 0) pref.y += tile.height;
      else if ((align & 0x000400) != 0) pref.y += fixd.y;
      else if ((align & 0x000800) != 0) pref.y += (tile.height * fixd.y + 500) / 1000;
      if ((align & 0x001000) != 0) pref.setBounds(0, pref.y, pref.x
            + pref.width, pref.height);
      else if ((align & 0x002000) != 0) pref.width = cont.width - pref.x;
      if ((align & 0x020000) != 0) pref.setBounds(pref.x, 0, pref.width, pref.y
            + pref.height);
      else if ((align & 0x040000) != 0) pref.height = cont.height - pref.y;
      if (insets != null) { // apply insets, if any:
         pref.x += insets.left;
         pref.y += insets.top;
         pref.width -= insets.left + insets.right;
         pref.height -= insets.top + insets.bottom;
      }
      // Note: this can cause surprising results, so use it, if you dare. :-)
      // Honour component minimum size:
      Dimension d = comp.getMinimumSize();
      if (pref.width < d.width) pref.width = d.width;
      if (pref.height < d.height) pref.height = d.height;
      comp.setBounds(pref); // now the tile is set!
   }
   /**
    * This constant specifies placement of the component even with the left
    * border of the provided reference component, otherwise to the container
    * itself.
    */
   public static final int NOINDENT = 0x000000;
   /**
    * This constant specifies placement of the component with its right border
    * one pixel to the left of the provided reference component, otherwise to
    * the container itself.
    */
   public static final int LEFTINDENT = 0x000001;
   /**
    * This constant specifies placement of the component evenly between the left
    * and right borders of the provided reference component, otherwise to the
    * container itself.
    */
   public static final int CENTERINDENT = 0x000002;
   /**
    * This constant specifies placement of the component with its right border
    * evenly aligned with the right border of the provided reference component,
    * otherwise to the container itself.
    */
   public static final int FULLINDENT = 0x000004;
   /**
    * This constant specifies placement of the left border of the component one
    * pixel to the right of the provided reference component origin, otherwise
    * to the container itself.
    */
   public static final int RIGHTINDENT = 0x000008;
   /**
    * Used in conjunction with a Rectangle constraint, the x value represents
    * the desired component indent as a fixed number of pixels right of the
    * provided component origin, otherwise to the container itself.
    */
   public static final int FIXEDINDENT = 0x000010;
   /**
    * Used in conjunction with a Rectangle constraint, the x value represents
    * the desired component indent as a percentage (2000 = 200.0%) of a provided
    * component, otherwise to the container itself.
    */
   public static final int PROPINDENT = 0x000020;
   /**
    * This constant specifies placement of the component even with the top
    * border of the provided reference component, otherwise to the container
    * itself.
    */
   public static final int NOOFFSET = 0x000000;
   /**
    * This constant specifies placement of the component with its bottom border
    * one pixel above the provided reference component, otherwise to the
    * container itself.
    */
   public static final int TOPOFFSET = 0x000040;
   /**
    * This constant specifies placement of the component evenly between the top
    * and bottom borders of the provided reference component, otherwise to the
    * container itself.
    */
   public static final int CENTEROFFSET = 0x000080;
   /**
    * This constant specifies placement of the component with its bottom border
    * evenly aligned with the bottom border of the provided reference component,
    * otherwise to the container itself.
    */
   public static final int FULLOFFSET = 0x000100;
   /**
    * This constant specifies placement of the top border of the component one
    * pixel below the provided reference component origin, otherwise to the
    * container itself.
    */
   public static final int BOTTOMOFFSET = 0x000200;
   /**
    * Used in conjunction with a Rectangle constraint, the y value represents
    * the desired component offset as a fixed number of pixels below the
    * provided component origin, otherwise to the container itself.
    */
   public static final int FIXEDOFFSET = 0x000400;
   /**
    * Used in conjunction with a Rectangle constraint, the y value represents
    * the desired component offset as a percentage (2000 = 200.0%) of a provided
    * component, otherwise to the container itself.
    */
   public static final int PROPOFFSET = 0x000800;
   /**
    * This constant specifies that the component have its preferred width, as
    * returned by its getPreferredSize method.
    */
   public static final int PREFWIDTH = 0x000000;
   /**
    * This constant specifies that the component be made wide enough such that
    * given its computed right margin, its left margin will align with that of
    * its container.
    */
   public static final int CLAMPLEFT = 0x001000;
   /**
    * This constant specifies that the component be made wide enough such that
    * given its computed origin, its right margin will align with that of its
    * container.
    */
   public static final int CLAMPRIGHT = 0x002000;
   /**
    * Used in conjunction with a Rectangle constraint, the width value
    * represents the desired component width as a fixed number of pixels.
    */
   public static final int FIXEDWIDTH = 0x004000;
   /**
    * Used in conjunction with a Rectangle constraint, the width value
    * represents the desired component offset as a percentage (2000 = 200.0%) of
    * a provided component, otherwise to the container itself.
    */
   public static final int PROPWIDTH = 0x008000;
   /**
    * This constant specifies that the component be made exactly as wide as its
    * reference component, otherwise as the container itself.
    */
   public static final int FULLWIDTH = 0x010000;
   /**
    * This constant specifies that the component have its preferred height, as
    * returned by its getPreferredSize method.
    */
   public static final int PREFHEIGHT = 0x000000;
   /**
    * This constant specifies that the component be made high enough such that
    * given its computed bottom margin, its top margin will align with that of
    * its container.
    */
   public static final int CLAMPTOP = 0x020000;
   /**
    * This constant specifies that the component be made high enough such that
    * given its computed origin, its bottom margin will align with that of its
    * container.
    */
   public static final int CLAMPBOTTOM = 0x040000;
   /**
    * Used in conjunction with a Rectangle constraint, the height value
    * represents the desired component width as a fixed number of pixels.
    */
   public static final int FIXEDHEIGHT = 0x080000;
   /**
    * Used in conjunction with a Rectangle constraint, the height value
    * represents the desired component offset as a percentage (2000 = 200.0%) of
    * a provided component, otherwise to the container itself.
    */
   public static final int PROPHEIGHT = 0x100000;
   /**
    * This constant specifies that the component be made exactly as high as its
    * reference component, otherwise as the container itself.
    */
   public static final int FULLHEIGHT = 0x200000;
   /**
    * A frequently used position, used in conjunction with a reference
    * component, it will locate the component directly over, with the same width
    * and height.
    */
   public static final Integer ABOVE = new Integer(NOINDENT + TOPOFFSET
         + FULLWIDTH + FULLHEIGHT);
   /**
    * A frequently used position, used in conjunction with a reference
    * component, it will locate the component directly beneath, with the same
    * width and height.
    */
   public static final Integer BELOW = new Integer(NOINDENT + BOTTOMOFFSET
         + FULLWIDTH + FULLHEIGHT);
   /**
    * A frequently used position, used in conjunction with a reference
    * component, it will locate the component directly adjacent, to its right,
    * with the same width and height.
    */
   public static final Integer RIGHT = new Integer(RIGHTINDENT + NOOFFSET
         + FULLWIDTH + FULLHEIGHT);
   /**
    * A frequently used position, used in conjunction with a reference
    * component, it will locate the component directly adjacent, to its left,
    * with the same width and height.
    */
   public static final Integer LEFT = new Integer(LEFTINDENT + NOOFFSET
         + FULLWIDTH + FULLHEIGHT);
   /**
    * A frequently used position, it will render the component using the exact
    * size of the reference component, or container.
    */
   public static final Integer FULLSIZE = new Integer(NOINDENT + NOOFFSET
         + FULLWIDTH + FULLHEIGHT);
   /**
    * Nothing is performed in the constructor, it is bodyless.
    */
   public TileLayout() {}
   /**
    * The primary component addition method. Components are added for layout,
    * and its constraints are provided as an Object array. Up to 4 constraints
    * may be specified, and their order is not important. The following are the
    * applicable constraints:
    * 


        * 


        * 

  •  Rectangle for fixed or proportional component bounds
        * 
  •  Insets to trim the final boundaries after computation
        * 
  •  Integer of TileLayout positioning constants
        * 
  •  Component for relative placement, instead of container
        * 

    * 
    * @param comp The component to be laid out within the container.
    * @param cons An Object[] containing 1 or more constraints.
    */
   public void addLayoutComponent(Component comp, Object cons) {
      components.add(comp);
      constraints.add(cons);
   }
   /**
    * This method will make the added component exactly the same size as the
    * container itself. It is useful for adding wallpaper.
    * 
    * @param comp The component to fill the container.
    * @param name The name of the component, unused by TileLayout.
    */
   public void addLayoutComponent(String name, Component comp) {
      components.add(comp);
      constraints.add(new Object[]{ FULLSIZE });
   }
   /**
    * As expected, removes the component from the ordered layout list.
    */
   public void removeLayoutComponent(Component comp) {
      for (int i = 0; i < components.size(); i++) {
         if (components.get(i) == comp) {
            components.remove(i);
            constraints.remove(i);
            return;
         }
      }
      throw new IllegalArgumentException("Component not in container");
   }
   /**
    * Lays out the components, last added to first added, according to their
    * specified constraints.
    */
   public void layoutContainer(Container parent) {
      Dimension container = parent.getSize();
      for (int i = components.size() - 1; i >= 0; i--)
         align(container, (Object[])constraints.get(i),
            (Component)components.get(i));
   }
   /**
    * Bodyless implementation, as TileLayout uses no cached information.
    */
   public void invalidateLayout(Container target) {}
   /**
    * Indicate center alignment.
    */
   public float getLayoutAlignmentX(Container target) { return 0.5F; }
   /**
    * Indicate center alignment.
    */
   public float getLayoutAlignmentY(Container target) { return 0.5F; }
   /**
    * Indicates no minimum size.
    */
   public Dimension minimumLayoutSize(Container parent) { return NONE; }
   /**
    * Indicates no maximum size.
    */
   public Dimension maximumLayoutSize(Container parent) { return NONE; }
   /**
    * Indicates no preferred size.
    */
   public Dimension preferredLayoutSize(Container parent) { return NONE; }
}