001    /* JAPI - (Yet another (hopefully) useful) Java API
002     *
003     * Copyright (C) 2004-2006 Christian Hujer
004     *
005     * This program is free software; you can redistribute it and/or
006     * modify it under the terms of the GNU General Public License as
007     * published by the Free Software Foundation; either version 2 of the
008     * License, or (at your option) any later version.
009     *
010     * This program is distributed in the hope that it will be useful, but
011     * WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013     * General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program; if not, write to the Free Software
017     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018     * 02111-1307, USA.
019     */
020    
021    package net.sf.japi.swing;
022    
023    import java.awt.Dimension;
024    import java.awt.Insets;
025    import java.awt.Component;
026    import java.awt.Container;
027    import java.awt.LayoutManager;
028    import org.jetbrains.annotations.NotNull;
029    import org.jetbrains.annotations.Nullable;
030    
031    /** Layout similar to FlowLayout, but using columns (vertical layout) instead of rows (horizontal layout).
032     * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
033     */
034    @SuppressWarnings({"NonPrivateFieldAccessedInSynchronizedContext", "FieldAccessedSynchronizedAndUnsynchronized"})
035    public class ColumnLayout implements LayoutManager {
036    
037        /** Horizontal Gap. */
038        private int hgap = 4;
039    
040        /** Vertical Gap. */
041        private int vgap = 4;
042    
043        /** Create a ColumnLayout with default gaps (4, 4). */
044        public ColumnLayout() {
045        }
046    
047        /** Create a ColumnLayout with defined gaps.
048         * @param hgap horizontal gap
049         * @param vgap vertical gap
050         */
051        public ColumnLayout(final int hgap, final int vgap) {
052            this.hgap = hgap;
053            this.vgap = vgap;
054        }
055    
056        /** Returns horizontal Gap.
057         * @return horizontal Gap.
058         */
059        public int getHgap() {
060            return hgap;
061        }
062    
063        /** Sets horizontal Gap.
064         * @param hgap horizontal Gap.
065         */
066        public void setHgap(final int hgap) {
067            this.hgap = hgap;
068        }
069    
070        /** Returns vertical Gap.
071         * @return vertical Gap.
072         */
073        public int getVgap() {
074            return vgap;
075        }
076    
077        /** Sets vertical Gap.
078         * @param vgap vertical Gap.
079         */
080        public void setVgap(final int vgap) {
081            this.vgap = vgap;
082        }
083    
084        /** {@inheritDoc} */
085        public void addLayoutComponent(@Nullable final String name, @Nullable final Component comp) {
086            // Superfluous
087        }
088    
089        /** {@inheritDoc} */
090        public void removeLayoutComponent(@Nullable final Component comp) {
091            // Superfluous
092        }
093    
094        /** {@inheritDoc} */
095        @NotNull public Dimension preferredLayoutSize(@NotNull final Container parent) {
096            synchronized (parent.getTreeLock()) {
097                final Dimension preferredLayoutSize = new Dimension();
098                final int nmembers = parent.getComponentCount();
099                for (int i = 0; i < nmembers; i++) {
100                    final Component comp = parent.getComponent(i);
101                    if (comp.isVisible()) {
102                        final Dimension dim = comp.getPreferredSize();
103                        preferredLayoutSize.width = Math.max(preferredLayoutSize.width, dim.width);
104                        if (i > 0) {
105                            preferredLayoutSize.height += vgap;
106                        }
107                        preferredLayoutSize.height += dim.height;
108                    }
109                }
110                final Insets insets = parent.getInsets();
111                preferredLayoutSize.width += insets.left + insets.right + (hgap << 1);
112                preferredLayoutSize.height += insets.top + insets.bottom + (vgap << 1);
113                return preferredLayoutSize;
114            }
115        }
116    
117        /** {@inheritDoc} */
118        @NotNull public Dimension minimumLayoutSize(@NotNull final Container parent) {
119            synchronized (parent.getTreeLock()) {
120                final Dimension minimumLayoutSize = new Dimension();
121                final int nmembers = parent.getComponentCount();
122                for (int i = 0; i < nmembers; i++) {
123                    final Component comp = parent.getComponent(i);
124                    if (comp.isVisible()) {
125                        final Dimension dim = comp.getMinimumSize();
126                        minimumLayoutSize.width = Math.max(minimumLayoutSize.width, dim.width);
127                        if (i > 0) {
128                            minimumLayoutSize.height += vgap;
129                        }
130                        minimumLayoutSize.height += dim.height;
131                    }
132                }
133                final Insets insets = parent.getInsets();
134                minimumLayoutSize.width += insets.left + insets.right + (hgap << 1);
135                minimumLayoutSize.height += insets.top + insets.bottom + (vgap << 1);
136                return minimumLayoutSize;
137            }
138        }
139    
140        /** {@inheritDoc} */
141        public void layoutContainer(@NotNull final Container parent) {
142            synchronized (parent.getTreeLock()) {
143                final Insets insets = parent.getInsets();
144                final int nmembers = parent.getComponentCount();
145                final int maxheight = parent.getHeight() - (insets.left + insets.right + (vgap << 1));
146                int maxwidth = 0;
147                int y = 0;
148                int x = insets.left + hgap;
149                for (int i = 0; i < nmembers; i++) {
150                    final Component comp = parent.getComponent(i);
151                    if (comp.isVisible()) {
152                        final Dimension dim = comp.getPreferredSize();
153                        comp.setSize(dim);
154                        if (y + vgap + comp.getHeight() > maxheight) {
155                            y = 0;
156                            x += maxwidth + hgap;
157                            maxwidth = 0;
158                        }
159                        maxwidth = comp.getWidth() > maxwidth ? comp.getWidth() : maxwidth;
160                        y += vgap;
161                        comp.setLocation(x, y);
162                        y += comp.getHeight();
163                    }
164                }
165            }
166        }
167    
168    } // class ColumnLayout