All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alee.extended.layout.WrapFlowLayout Maven / Gradle / Ivy

/*
 * This file is part of WebLookAndFeel library.
 *
 * WebLookAndFeel library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * WebLookAndFeel library 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with WebLookAndFeel library.  If not, see .
 */

package com.alee.extended.layout;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;

/**
 * @author Mikle Garin
 */

public class WrapFlowLayout extends AbstractLayoutManager implements SwingConstants
{
    // todo support RTL + LEADING/TRAILING support

    protected boolean fitWidth = true;
    protected boolean fillWidth = true;
    protected int hgap = 0;
    protected int vgap = 0;
    protected int halign = LEFT;
    protected int valign = TOP;
    protected boolean wrapEachComponent = false;

    protected int maxWidth = 0;
    protected int maxHeight = 0;
    protected ArrayList rowsData;

    public WrapFlowLayout ()
    {
        this ( false );
    }

    public WrapFlowLayout ( final boolean fillWidth )
    {
        this ( fillWidth, 0, 0 );
    }

    public WrapFlowLayout ( final int hgap, final int vgap )
    {
        this ( false, hgap, vgap );
    }

    public WrapFlowLayout ( final boolean fillWidth, final int hgap, final int vgap )
    {
        super ();
        this.fillWidth = fillWidth;
        this.hgap = hgap;
        this.vgap = vgap;
    }

    public boolean isFitWidth ()
    {
        return fitWidth;
    }

    public void setFitWidth ( final boolean fitWidth )
    {
        this.fitWidth = fitWidth;
    }

    public boolean isFillWidth ()
    {
        return fillWidth;
    }

    public void setFillWidth ( final boolean fillWidth )
    {
        this.fillWidth = fillWidth;
    }

    public int getHgap ()
    {
        return hgap;
    }

    public void setHgap ( final int hgap )
    {
        this.hgap = hgap;
    }

    public int getVgap ()
    {
        return vgap;
    }

    public void setVgap ( final int vgap )
    {
        this.vgap = vgap;
    }

    public int getHalign ()
    {
        return halign;
    }

    public void setHalign ( final int halign )
    {
        this.halign = halign;
    }

    public int getValign ()
    {
        return valign;
    }

    public void setValign ( final int valign )
    {
        this.valign = valign;
    }

    public boolean isWrapEachComponent ()
    {
        return wrapEachComponent;
    }

    public void setWrapEachComponent ( final boolean wrapEachComponent )
    {
        this.wrapEachComponent = wrapEachComponent;
    }

    public int getMaxWidth ()
    {
        return maxWidth;
    }

    public int getMaxHeight ()
    {
        return maxHeight;
    }

    public ArrayList getRowsData ()
    {
        return rowsData;
    }

    @Override
    public Dimension preferredLayoutSize ( final Container parent )
    {
        layoutContainer ( parent );
        return new Dimension ( maxWidth, maxHeight );
    }

    @Override
    public Dimension minimumLayoutSize ( final Container parent )
    {
        layoutContainer ( parent );
        return new Dimension ( 0, maxHeight );
    }

    @Override
    public void layoutContainer ( final Container parent )
    {
        // Ignore if no children
        if ( parent.getComponentCount () == 0 )
        {
            maxWidth = 0;
            maxHeight = 0;
            rowsData = new ArrayList ( 0 );
            return;
        }

        // Parent properties
        final Insets insets = parent.getInsets ();
        final int parentWidth = parent.getWidth () - insets.left - insets.right;

        // Current row
        int currentRow = 0;

        // Current processed row component number
        int componentInRow = 0;

        // Total width & height
        maxWidth = 0;
        maxHeight = 0;

        // Current processed row width & height
        int currentRowWidth = 0;
        int currentRowMaxHeight = 0;

        // Computing rows and components
        rowsData = new ArrayList ();
        for ( int i = 0; i < parent.getComponentCount (); i++ )
        {
            final Component component = parent.getComponent ( i );
            final Dimension ps = component.getPreferredSize ();
            if ( componentInRow > 0 && ( isWrapEachComponent () || currentRowWidth + hgap + ps.width > parentWidth ) )
            {
                // Saving row settings
                rowsData.get ( currentRow ).setWidth ( currentRowWidth );
                rowsData.get ( currentRow ).setHeight ( currentRowMaxHeight );

                // Saving max sizes
                maxWidth = Math.max ( maxWidth, currentRowWidth );
                maxHeight += ( currentRow > 0 ? vgap : 0 ) + currentRowMaxHeight;

                componentInRow = 0;
                currentRowWidth = 0;
                currentRowMaxHeight = 0;
                currentRow++;
            }

            final int componentWidth = fitWidth ? Math.min ( ps.width, parentWidth ) : ps.width;
            currentRowWidth += ( componentInRow > 0 ? hgap : 0 ) + componentWidth;
            currentRowMaxHeight = Math.max ( currentRowMaxHeight, ps.height );
            componentInRow++;

            if ( currentRow >= rowsData.size () )
            {
                rowsData.add ( new RowData () );
            }
            rowsData.get ( currentRow ).addComponent ( component );
        }
        rowsData.get ( currentRow ).setWidth ( currentRowWidth );
        rowsData.get ( currentRow ).setHeight ( currentRowMaxHeight );
        maxHeight += ( currentRow > 0 ? vgap : 0 ) + currentRowMaxHeight;
        maxHeight += insets.top + insets.bottom;

        // Layouting components
        int x;
        int y = getStartY ( parent, insets );
        for ( final RowData row : rowsData )
        {
            x = getStartX ( parent, insets, row );
            int i = 0;
            for ( final Component component : row.getComponents () )
            {
                final Dimension ps = component.getPreferredSize ();

                int componentWidth = fitWidth ? Math.min ( ps.width, parentWidth ) : ps.width;
                if ( fillWidth && i + 1 == row.getComponents ().size () && halign == LEFT )
                {
                    componentWidth = insets.left + parentWidth - x;
                }
                component.setBounds ( x, y, componentWidth, row.getHeight () );

                x += componentWidth + hgap;
                i++;
            }
            y += row.getHeight () + vgap;
        }
    }

    protected int getStartX ( final Container parent, final Insets insets, final RowData row )
    {
        final int x;
        if ( fillWidth || halign == LEFT )
        {
            x = insets.left;
        }
        else if ( halign == RIGHT )
        {
            x = parent.getWidth () - insets.right - row.getWidth ();
        }
        else
        {
            x = parent.getWidth () / 2 - row.getWidth () / 2;
        }
        return x;
    }

    protected int getStartY ( final Container parent, final Insets insets )
    {
        final int y;
        if ( valign == TOP )
        {
            y = insets.top;
        }
        else if ( valign == BOTTOM )
        {
            y = parent.getHeight () - insets.bottom - maxHeight;
        }
        else
        {
            y = insets.top + parent.getHeight () / 2 - maxHeight / 2;
        }
        return y;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy