001    /* JAPI - (Yet anothr (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    
030    /** Layout similar to FlowLayout, but using columns (vertical layout) instead of rows (horizontal layout).
031     * @author <a href="mailto:chris@itcqis.com">Christian Hujer</a>
032     */
033    @SuppressWarnings({"NonPrivateFieldAccessedInSynchronizedContext", "FieldAccessedSynchronizedAndUnsynchronized"})
034    public class ColumnLayout implements LayoutManager {
035    
036        /** Horizontal Gap. */
037        private int hgap = 4;
038    
039        /** Vertical Gap. */
040        private int vgap = 4;
041    
042        /** Create a ColumnLayout with default gaps (4, 4). */
043        public ColumnLayout() {
044        }
045    
046        /** Create a ColumnLayout with defined gaps.
047         * @param hgap horizontal gap
048         * @param vgap vertical gap
049         */
050        public ColumnLayout(final int hgap, final int vgap) {
051            this.hgap = hgap;
052            this.vgap = vgap;
053        }
054    
055        /** Returns horizontal Gap.
056         * @return horizontal Gap.
057         */
058        public int getHgap() {
059            return hgap;
060        }
061    
062        /** Sets horizontal Gap.
063         * @param hgap horizontal Gap.
064         */
065        public void setHgap(final int hgap) {
066            this.hgap = hgap;
067        }
068    
069        /** Returns vertical Gap.
070         * @return vertical Gap.
071         */
072        public int getVgap() {
073            return vgap;
074        }
075    
076        /** Sets vertical Gap.
077         * @param vgap vertical Gap.
078         */
079        public void setVgap(final int vgap) {
080            this.vgap = vgap;
081        }
082    
083        /** {@inheritDoc} */
084        public void addLayoutComponent(final String name, final Component comp) {
085            // Superfluous
086        }
087    
088        /** {@inheritDoc} */
089        public void removeLayoutComponent(final Component comp) {
090            // Superfluous
091        }
092    
093        /** {@inheritDoc} */
094        public Dimension preferredLayoutSize(@NotNull final Container parent) {
095            synchronized (parent.getTreeLock()) {
096                final Dimension preferredLayoutSize = new Dimension();
097                final int nmembers = parent.getComponentCount();
098                for (int i = 0; i < nmembers; i++) {
099                    final Component comp = parent.getComponent(i);
100                    if (comp.isVisible()) {
101                        final Dimension dim = comp.getPreferredSize();
102                        preferredLayoutSize.width = Math.max(preferredLayoutSize.width, dim.width);
103                        if (i > 0) {
104                            preferredLayoutSize.height += vgap;
105                        }
106                        preferredLayoutSize.height += dim.height;
107                    }
108                }
109                final Insets insets = parent.getInsets();
110                preferredLayoutSize.width += insets.left + insets.right + (hgap << 1);
111                preferredLayoutSize.height += insets.top + insets.bottom + (vgap << 1);
112                return preferredLayoutSize;
113            }
114        }
115    
116        /** {@inheritDoc} */
117        public Dimension minimumLayoutSize(final Container parent) {
118            synchronized (parent.getTreeLock()) {
119                final Dimension minimumLayoutSize = new Dimension();
120                final int nmembers = parent.getComponentCount();
121                for (int i = 0; i < nmembers; i++) {
122                    final Component comp = parent.getComponent(i);
123                    if (comp.isVisible()) {
124                        final Dimension dim = comp.getMinimumSize();
125                        minimumLayoutSize.width = Math.max(minimumLayoutSize.width, dim.width);
126                        if (i > 0) {
127                            minimumLayoutSize.height += vgap;
128                        }
129                        minimumLayoutSize.height += dim.height;
130                    }
131                }
132                final Insets insets = parent.getInsets();
133                minimumLayoutSize.width += insets.left + insets.right + (hgap << 1);
134                minimumLayoutSize.height += insets.top + insets.bottom + (vgap << 1);
135                return minimumLayoutSize;
136            }
137        }
138    
139        /** {@inheritDoc} */
140        public void layoutContainer(final Container parent) {
141            synchronized (parent.getTreeLock()) {
142                final Insets insets = parent.getInsets();
143                final int nmembers = parent.getComponentCount();
144                final int maxheight = parent.getHeight() - (insets.left + insets.right + (vgap << 1));
145                int maxwidth = 0;
146                int y = 0;
147                int x = insets.left + hgap;
148                for (int i = 0; i < nmembers; i++) {
149                    final Component comp = parent.getComponent(i);
150                    if (comp.isVisible()) {
151                        final Dimension dim = comp.getPreferredSize();
152                        comp.setSize(dim);
153                        if (y + vgap + comp.getHeight() > maxheight) {
154                            y = 0;
155                            x += maxwidth + hgap;
156                            maxwidth = 0;
157                        }
158                        maxwidth = comp.getWidth() > maxwidth ? comp.getWidth() : maxwidth;
159                        y += vgap;
160                        comp.setLocation(x, y);
161                        y += comp.getHeight();
162                    }
163                }
164            }
165        }
166    
167    } // class ColumnLayout