    001    /* ========================================================================
    002     * JCommon : a free general purpose class library for the Java(tm) platform
    003     * ========================================================================
    004     *
    005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
    006     *
    007     * Project Info:  http://www.jfree.org/jcommon/index.html
    008     *
    009     * This library is free software; you can redistribute it and/or modify it
    010     * under the terms of the GNU Lesser General Public License as published by
    011     * the Free Software Foundation; either version 2.1 of the License, or
    012     * (at your option) any later version.
    013     *
    014     * This library is distributed in the hope that it will be useful, but
    015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    017     * License for more details.
    018     *
    019     * You should have received a copy of the GNU Lesser General Public
    020     * License along with this library; if not, write to the Free Software
    021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    022     * USA.
    023     *
    024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
    025     * in the United States and other countries.]
    026     *
    027     * --------------
    028     * LCBLayout.java
    029     * --------------
    030     * (C) Copyright 2000-2005, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * $Id: LCBLayout.java,v 1.4 2005/10/18 13:16:50 mungady Exp $
    036     *
    037     * Changes (from 26-Oct-2001)
    038     * --------------------------
    039     * 26-Oct-2001 : Changed package to com.jrefinery.layout.* (DG);
    040     * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG);
    041     */
    042
    043    package org.jfree.layout;
    044
    045    import java.awt.Component;
    046    import java.awt.Container;
    047    import java.awt.Dimension;
    048    import java.awt.Insets;
    049    import java.awt.LayoutManager;
    050    import java.io.Serializable;
    051
    052    /**
    053     * Specialised layout manager for a grid of components.
    054     *
    055     * @author David Gilbert
    056     */
    057    public class LCBLayout implements LayoutManager, Serializable {
    058
    059        /** For serialization. */
    060        private static final long serialVersionUID = -2531780832406163833L;
    061
    062        /** A constant for the number of columns in the layout. */
    063        private static final int COLUMNS = 3;
    064
    065        /** Tracks the column widths. */
    066        private int[] colWidth;
    067
    068        /** Tracks the row heights. */
    069        private int[] rowHeight;
    070
    071        /** The gap between each label and component. */
    072        private int labelGap;
    073
    074        /** The gap between each component and button. */
    075        private int buttonGap;
    076
    077        /** The gap between rows. */
    078        private int vGap;
    079
    080        /**
    081         * Creates a new LCBLayout with the specified maximum number of rows.
    082         *
    083         * @param maxrows  the maximum number of rows.
    084         */
    085        public LCBLayout(final int maxrows) {
    086            this.labelGap = 10;
    087            this.buttonGap = 6;
    088            this.vGap = 2;
    089            this.colWidth = new int[COLUMNS];
    090            this.rowHeight = new int[maxrows];
    091        }
    092
    093        /**
    094         * Returns the preferred size using this layout manager.
    095         *
    096         * @param parent  the parent.
    097         *
    098         * @return the preferred size using this layout manager.
    099        */
    100        public Dimension preferredLayoutSize(final Container parent) {
    101
    102            synchronized (parent.getTreeLock()) {
    103                final Insets insets = parent.getInsets();
    104                final int ncomponents = parent.getComponentCount();
    105                final int nrows = ncomponents / COLUMNS;
    106                for (int c = 0; c < COLUMNS; c++) {
    107                    for (int r = 0; r < nrows; r++) {
    108                        final Component component
    109                            = parent.getComponent(r * COLUMNS + c);
    110                        final Dimension d = component.getPreferredSize();
    111                        if (this.colWidth[c] < d.width) {
    112                            this.colWidth[c] = d.width;
    113                        }
    114                        if (this.rowHeight[r] < d.height) {
    115                            this.rowHeight[r] = d.height;
    116                        }
    117                    }
    118                }
    119                int totalHeight = this.vGap * (nrows - 1);
    120                for (int r = 0; r < nrows; r++) {
    121                    totalHeight = totalHeight + this.rowHeight[r];
    122                }
    123                final int totalWidth = this.colWidth[0] + this.labelGap
    124                    + this.colWidth[1] + this.buttonGap + this.colWidth[2];
    125                return new Dimension(
    126                    insets.left + insets.right + totalWidth + this.labelGap
    127                        + this.buttonGap,
    128                    insets.top + insets.bottom + totalHeight + this.vGap
    129                );
    130            }
    131
    132        }
    133
    134        /**
    135         * Returns the minimum size using this layout manager.
    136         *
    137         * @param parent  the parent.
    138         *
    139         * @return the minimum size using this layout manager.
    140         */
    141        public Dimension minimumLayoutSize(final Container parent) {
    142
    143            synchronized (parent.getTreeLock()) {
    144                final Insets insets = parent.getInsets();
    145                final int ncomponents = parent.getComponentCount();
    146                final int nrows = ncomponents / COLUMNS;
    147                for (int c = 0; c < COLUMNS; c++) {
    148                    for (int r = 0; r < nrows; r++) {
    149                        final Component component
    150                            = parent.getComponent(r * COLUMNS + c);
    151                        final Dimension d = component.getMinimumSize();
    152                        if (this.colWidth[c] < d.width) {
    153                            this.colWidth[c] = d.width;
    154                        }
    155                        if (this.rowHeight[r] < d.height) {
    156                            this.rowHeight[r] = d.height;
    157                        }
    158                    }
    159                }
    160                int totalHeight = this.vGap * (nrows - 1);
    161                for (int r = 0; r < nrows; r++) {
    162                    totalHeight = totalHeight + this.rowHeight[r];
    163                }
    164                final int totalWidth = this.colWidth[0] + this.labelGap
    165                    + this.colWidth[1] + this.buttonGap + this.colWidth[2];
    166                return new Dimension(
    167                    insets.left + insets.right + totalWidth + this.labelGap
    168                    + this.buttonGap,
    169                    insets.top + insets.bottom + totalHeight + this.vGap
    170                );
    171            }
    172
    173        }
    174
    175        /**
    176         * Lays out the components.
    177         *
    178         * @param parent  the parent.
    179         */
    180        public void layoutContainer(final Container parent) {
    181
    182            synchronized (parent.getTreeLock()) {
    183                final Insets insets = parent.getInsets();
    184                final int ncomponents = parent.getComponentCount();
    185                final int nrows = ncomponents / COLUMNS;
    186                for (int c = 0; c < COLUMNS; c++) {
    187                    for (int r = 0; r < nrows; r++) {
    188                        final Component component
    189                            = parent.getComponent(r * COLUMNS + c);
    190                        final Dimension d = component.getPreferredSize();
    191                        if (this.colWidth[c] < d.width) {
    192                            this.colWidth[c] = d.width;
    193                        }
    194                        if (this.rowHeight[r] < d.height) {
    195                            this.rowHeight[r] = d.height;
    196                        }
    197                    }
    198                }
    199                int totalHeight = this.vGap * (nrows - 1);
    200                for (int r = 0; r < nrows; r++) {
    201                    totalHeight = totalHeight + this.rowHeight[r];
    202                }
    203                final int totalWidth = this.colWidth[0] + this.colWidth[1]
    204                                                        + this.colWidth[2];
    205
    206                // adjust the width of the second column to use up all of parent
    207                final int available = parent.getWidth() - insets.left
    208                    - insets.right - this.labelGap - this.buttonGap;
    209                this.colWidth[1] = this.colWidth[1] + (available - totalWidth);
    210
    211                // *** DO THE LAYOUT ***
    212                int x = insets.left;
    213                for (int c = 0; c < COLUMNS; c++) {
    214                    int y = insets.top;
    215                    for (int r = 0; r < nrows; r++) {
    216                        final int i = r * COLUMNS + c;
    217                        if (i < ncomponents) {
    218                            final Component component = parent.getComponent(i);
    219                            final Dimension d = component.getPreferredSize();
    220                            final int h = d.height;
    221                            final int adjust = (this.rowHeight[r] - h) / 2;
    222                            parent.getComponent(i).setBounds(x, y + adjust,
    223                                    this.colWidth[c], h);
    224                        }
    225                        y = y + this.rowHeight[r] + this.vGap;
    226                    }
    227                    x = x + this.colWidth[c];
    228                    if (c == 0) {
    229                        x = x + this.labelGap;
    230                    }
    231                    if (c == 1) {
    232                        x = x + this.buttonGap;
    233                    }
    234                }
    235
    236            }
    237
    238        }
    239
    240        /**
    241         * Not used.
    242         *
    243         * @param comp  the component.
    244         */
    245        public void addLayoutComponent(final Component comp) {
    246            // not used
    247        }
    248
    249        /**
    250         * Not used.
    251         *
    252         * @param comp  the component.
    253         */
    254        public void removeLayoutComponent(final Component comp) {
    255            // not used
    256        }
    257
    258        /**
    259         * Not used.
    260         *
    261         * @param name  the component name.
    262         * @param comp  the component.
    263         */
    264        public void addLayoutComponent(final String name, final Component comp) {
    265            // not used
    266        }
    267
    268        /**
    269         * Not used.
    270         *
    271         * @param name  the component name.
    272         * @param comp  the component.
    273         */
    274        public void removeLayoutComponent(final String name, final Component comp) {
    275            // not used
    276        }
    277
    278    }