1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * ident        "%Z%%M% %I%     %E% SMI"
  24  *
  25  * Copyright (c) 1996-1999 by Sun Microsystems, Inc.
  26  * All rights reserved.
  27  */
  28 package com.sun.dhcpmgr.ui;
  29 
  30 import java.awt.*;
  31 
  32 /**
  33  * <CODE>ButtonLayout</CODE> is used to layout buttons in a
  34  * <CODE>Panel</CODE>. It will arrange buttons left to right
  35  * until no more buttons fit on the same line.  Each line is
  36  * centered. All buttons are set to an equal size.<P>
  37  *
  38  * While <CODE>ButtonLayout</CODE> was designed for <CODE>Buttons</CODE>,
  39  * any component can be added to the layout. All components are
  40  * set to an equal size.<P>
  41  * 
  42  */
  43 public class ButtonLayout implements LayoutManager {
  44 
  45     ALIGNMENT align;
  46     int hgap;
  47     int vgap;
  48 
  49     /**
  50      * Constructs a new <CODE>ButtonLayout</CODE> with a centered alignment.
  51      */
  52     public ButtonLayout() {
  53         this(ALIGNMENT.CENTER, 5, 5);
  54     }
  55 
  56     /**
  57      * Constructs a new <CODE>ButtonLayout</CODE> with the specified alignment.
  58      * @param <VAR>align</VAR> The alignment value.
  59      * @see ALIGNMENT
  60      */
  61     public ButtonLayout(ALIGNMENT align) {
  62         this(align, 5, 5);
  63     }
  64 
  65     /**
  66      * Constructs a new <CODE>ButtonLayout</CODE> with the specified
  67      * alignment and gap values.
  68      * @param <VAR>align</VAR> The alignment value.
  69      * @param <VAR>hgap</VAR> The horizontal gap variable.
  70      * @param <VAR>vgap</VAR> The vertical gap variable.
  71      * @see ALIGNMENT
  72      */
  73     public ButtonLayout(ALIGNMENT align, int hgap, int vgap) {
  74         this.align = align;
  75         this.hgap = hgap;
  76         this.vgap = vgap;
  77     }
  78 
  79     /**
  80      * Adds the specified component to the layout. This is not
  81      *used by this class.
  82      * @param <VAR>name</VAR>       The name of the component.
  83      * @param <VAR>comp</VAR>       The component to be added.
  84      */
  85     public void addLayoutComponent(String name, Component comp) {
  86     }
  87 
  88     /**
  89      * Removes the specified component from the layout. This
  90      * is not used by this class.  
  91      * @param <VAR>comp</VAR>       The component to remove.
  92      */
  93     public void removeLayoutComponent(Component comp) {
  94     }
  95 
  96     /**
  97      * Returns the preferred dimensions for this layout given
  98      * the components in the specified target container.
  99      * @param <VAR>target</VAR>     The component that needs to be laid out.
 100      * @see java.awt.Container
 101      * @see #minimumLayoutSize
 102      */
 103     public Dimension preferredLayoutSize(Container target) {
 104         Dimension dim = new Dimension(0, 0);
 105         int nmembers = target.getComponentCount();
 106 
 107         for (int i = 0; i < nmembers; i++) {
 108             Component m = target.getComponent(i);
 109             if (m.isVisible()) {
 110                 Dimension d = m.getPreferredSize();
 111                 dim.height = Math.max(dim.height, d.height);
 112                 dim.width = Math.max(dim.width, d.width);
 113             }
 114         }
 115         dim.width = (dim.width*nmembers) + (hgap*nmembers-1);
 116         Insets insets = target.getInsets();
 117         dim.width += insets.left + insets.right + hgap*2;
 118         dim.height += insets.top + insets.bottom + vgap*2;
 119         return dim;
 120     }
 121 
 122     /**
 123      * Returns the minimum dimensions needed to layout the components
 124      * contained in the specified target container.
 125      * @param <VAR>target</VAR>     The component that needs to be laid out 
 126      * @see #preferredLayoutSize
 127      */
 128     public Dimension minimumLayoutSize(Container target) {
 129         Dimension dim = new Dimension(0, 0);
 130         int nmembers = target.getComponentCount();
 131 
 132         for (int i = 0; i < nmembers; i++) {
 133             Component m = target.getComponent(i);
 134             if (m.isVisible()) {
 135                 Dimension d = m.getMinimumSize();
 136                 dim.height = Math.max(dim.height, d.height);
 137                 dim.width = Math.max(dim.width, d.width);
 138             }
 139         }
 140         dim.width = (dim.width*nmembers) + (hgap*nmembers-1);
 141         Insets insets = target.getInsets();
 142         dim.width += insets.left + insets.right + hgap*2;
 143         dim.height += insets.top + insets.bottom + vgap*2;
 144         return dim;
 145     }
 146 
 147     /** 
 148      * Centers the elements in the specified row, if there is any slack.
 149      * @param <VAR>target</VAR>     The component which needs to be moved.
 150      * @param <VAR>x</VAR>  The x coordinate.
 151      * @param <VAR>y</VAR>  The y coordinate.
 152      * @param <VAR>width</VAR>      The width dimensions.
 153      * @param <VAR>height</VAR>     The height dimensions.
 154      * @param <VAR>rowStart</VAR>   Index of the first component in the row.
 155      * @param <VAR>rowEnd</VAR>     Index of the last component in the row.
 156      */
 157     private void moveComponents(Container target, int x, int y, int width,
 158                                 int height, int rowStart, int rowEnd) {
 159         Dimension dim;
 160 
 161         if (align == ALIGNMENT.LEFT) {
 162             // do nothing
 163         } else if (align == ALIGNMENT.CENTER) {
 164             x += width / 2;
 165         } else if (align == ALIGNMENT.RIGHT) {
 166             x += width;
 167         }
 168         for (int i = rowStart; i < rowEnd; i++) {
 169             Component m = target.getComponent(i);
 170             if (m.isVisible()) {
 171                 dim = m.getSize();
 172                 m.setLocation(x, y + (height - dim.height) / 2);
 173                 x += hgap + dim.width;
 174             }
 175         }
 176     }
 177 
 178     /**
 179      * Lays out the container. This method will actually reshape the
 180      * components in the target in order to satisfy the constraints of
 181      * the <CODE>BorderLayout</CODE> object. 
 182      * @param <VAR>target</VAR>     The specified component being laid out.
 183      * @see java.awt.Container
 184      */
 185     public void layoutContainer(Container target) {
 186         Insets insets = target.getInsets();
 187         Dimension tdim = target.getSize();
 188         int maxwidth = tdim.width - (insets.left + insets.right + hgap*2);
 189         int nmembers = target.getComponentCount();
 190         int x = 0, y = insets.top + vgap;
 191         int rowh = 0, start = 0;
 192         Dimension dim = new Dimension(0, 0);
 193 
 194         for (int i = 0; i < nmembers; i++) {
 195             Component m = target.getComponent(i);
 196             if (m.isVisible()) {
 197                 Dimension d = m.getMinimumSize();
 198                 dim.width = Math.max(dim.width, d.width);
 199             }
 200         }
 201         for (int i = 0; i < nmembers; i++) {
 202             Component m = target.getComponent(i);
 203             if (m.isVisible()) {
 204                 Dimension d = m.getPreferredSize();
 205                 m.setSize(dim.width, d.height);
 206         
 207                 if ((x == 0) || ((x + dim.width) <= maxwidth)) {
 208                     if (x > 0) {
 209                         x += hgap;
 210                     }
 211                     x += dim.width;
 212                     rowh = Math.max(rowh, d.height);
 213                 } else {
 214                     moveComponents(target, insets.left + hgap, y, maxwidth - x,
 215                         rowh, start, i);
 216                     x = dim.width;
 217                     y += vgap + rowh;
 218                     rowh = d.height;
 219                     start = i;
 220                 }
 221             }
 222         }
 223         moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh,
 224             start, nmembers);
 225     }
 226     
 227     /**
 228      * Returns the <CODE>String</CODE> representation of this
 229      * <CODE>ButtonLayout</CODE>'s values.
 230      */
 231     public String toString() {
 232         String str = "";
 233         if (align == ALIGNMENT.LEFT) {
 234             str = ",align=left";
 235         } else if (align == ALIGNMENT.RIGHT) {
 236             str = ",align=right";
 237         } else if (align == ALIGNMENT.CENTER) {
 238             str = ",align=center";
 239         }
 240         return getClass().getName()
 241             + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";
 242     }
 243 }