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

com.alee.extended.split.MultiSplitLayoutHelper 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.split;

import com.alee.utils.swing.SizeType;

import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * {@link WebMultiSplitPaneModel} layout helper.
 * It calculates and provides easy access to some of the basic parameters used to layout {@link WebMultiSplitPane} contents.
 *
 * @author Mikle Garin
 * @see How to use WebMultiSplitPane
 * @see WebMultiSplitPaneModel
 * @see WebMultiSplitPane
 */

public class MultiSplitLayoutHelper
{
    /**
     * Preferred sizes of all components.
     */
    protected Map preferredSizes;

    /**
     * Minimum sizes of all components.
     */
    protected Map minimumSizes;

    /**
     * Maximum sizes of all components.
     */
    protected Map maximumSizes;

    /**
     * Returns {@link Component} size for the specified {@link SizeType}.
     *
     * @param component {@link Component}
     * @param sizeType  {@link SizeType}
     * @return {@link Component} size for the specified {@link SizeType}
     */
    public Dimension size ( final Component component, final SizeType sizeType )
    {
        final Dimension size;
        switch ( sizeType )
        {
            case minimum:
            {
                if ( minimumSizes == null )
                {
                    minimumSizes = new HashMap ( 1 );
                }
                if ( !minimumSizes.containsKey ( component ) )
                {
                    minimumSizes.put ( component, component.getMinimumSize () );
                }
                size = minimumSizes.get ( component );
                break;
            }
            case maximum:
            {
                if ( maximumSizes == null )
                {
                    maximumSizes = new HashMap ( 1 );
                }
                if ( !maximumSizes.containsKey ( component ) )
                {
                    maximumSizes.put ( component, component.getMaximumSize () );
                }
                size = maximumSizes.get ( component );
                break;
            }
            default:
            case preferred:
            {
                if ( preferredSizes == null )
                {
                    preferredSizes = new HashMap ( 1 );
                }
                if ( !preferredSizes.containsKey ( component ) )
                {
                    preferredSizes.put ( component, component.getPreferredSize () );
                }
                size = preferredSizes.get ( component );
            }
        }
        return size;
    }

    /**
     * Helper used for calculating initial {@link MultiSplitViewState}s.
     * Also used for calculating {@link WebMultiSplitPane} minimum, preferred and maximum sizes.
     * Calculations in this helper rely only on {@link MultiSplitConstraints} and do not take {@link MultiSplitViewState} into account.
     */
    public static class Static extends MultiSplitLayoutHelper
    {
        /**
         * Whether or not {@link WebMultiSplitPane}s are placed horizontally.
         */
        public final boolean horizontal;

        /**
         * Space available for {@link MultiSplitView}s.
         * This doesn't include insets and divider sizes.
         */
        public final int space;

        /**
         * Space available for percentage {@link MultiSplitView}s only.
         * It always has {@code 0} or larger value.
         */
        public final int spaceForPercentViews;

        /**
         * Sum of all percent based {@link MultiSplitView}s.
         * It also includes {@link MultiSplitView}s added under {@link MultiSplitConstraints#FILL} constraints.
         */
        public final double totalPercentViews;

        /**
         * Sum of all weights for {@link MultiSplitView}s.
         */
        public final double totalWeights;

        /**
         * Calculated percent representation for each of {@link MultiSplitConstraints#FILL} constraints.
         */
        public final double fillViewSize;

        /**
         * Constructs new {@link Static}.
         *
         * @param multiSplitPane {@link WebMultiSplitPane}
         * @param views          {@link List} containing {@link MultiSplitView}s
         * @param sizeType       {@link SizeType} describing method requesting help
         */
        public Static ( final WebMultiSplitPane multiSplitPane, final List views, final SizeType sizeType )
        {
            // Basic settings
            this.horizontal = multiSplitPane.getOrientation ().isHorizontal ();

            // Space available for the views
            final Insets insets = multiSplitPane.getInsets ();
            final int dividersCount = views.size () - 1;
            final int dividersSpace = multiSplitPane.getDividerSize () * dividersCount;
            this.space = Math.max ( 0, horizontal ?
                    multiSplitPane.getWidth () - insets.left - insets.right - dividersSpace :
                    multiSplitPane.getHeight () - insets.top - insets.bottom - dividersSpace );

            // Views sizes
            int totalPixelViews = 0;
            double totalPercentViews = 0.0;
            int fillViewsCount = 0;
            double totalWeights = 0.0;
            for ( final MultiSplitView view : views )
            {
                final Component component = view.component ();
                final MultiSplitConstraints constraints = view.constraints ();

                // Views sizes
                if ( constraints.isPixels () )
                {
                    totalPixelViews += constraints.pixels ();
                }
                else if ( constraints.isPercents () )
                {
                    totalPercentViews += constraints.percents ();
                }
                else if ( constraints.isFill () )
                {
                    fillViewsCount++;
                }
                else if ( constraints.isPreferred () )
                {
                    final Dimension ps = size ( component, SizeType.preferred );
                    totalPixelViews += horizontal ? ps.width : ps.height;
                }
                else if ( constraints.isMinimum () )
                {
                    final Dimension ms = size ( component, SizeType.minimum );
                    totalPixelViews += horizontal ? ms.width : ms.height;
                }
                else
                {
                    throw new IllegalArgumentException ( "Unknown view size value: " + constraints.size () );
                }

                // Weights
                totalWeights += constraints.weight ();
            }
            this.totalWeights = totalWeights;

            // Variables for normalizing percentage and fill views
            this.fillViewSize = totalPercentViews > 0.0 ? totalPercentViews : 1.0;
            this.totalPercentViews = totalPercentViews + fillViewSize * fillViewsCount;

            // Space available for percentage views
            spaceForPercentViews = Math.max ( 0, space - totalPixelViews );
        }
    }

    /**
     * Helper used for calculating runtime variables for {@link WebMultiSplitPane} layout.
     * Calculations in this helper rely only on both {@link MultiSplitViewState} and {@link MultiSplitConstraints}.
     */
    public static class Runtime
    {
        /**
         * Space available for {@link MultiSplitView}s.
         * This doesn't include insets and divider sizes.
         */
        public final int space;

        /**
         * Sum of all {@link MultiSplitView}s sizes.
         */
        public final int totalSizes;

        /**
         * Sum of all {@link MultiSplitView}s weights.
         */
        public final double totalWeights;

        /**
         * Amount of {@link MultiSplitView}s with non-zero size.
         */
        public final int nonZeroViews;

        /**
         * Sum of all weights for {@link MultiSplitView}s with non-zero size.
         */
        public final double nonZeroViewsWeights;

        /**
         * Constructs new {@link Static}.
         *
         * @param multiSplitPane {@link WebMultiSplitPane}
         * @param views          {@link List} containing {@link MultiSplitView}s
         */
        public Runtime ( final WebMultiSplitPane multiSplitPane, final List views )
        {
            // Space available for the views
            final Insets insets = multiSplitPane.getInsets ();
            final int dividersCount = views.size () - 1;
            final int dividersSpace = multiSplitPane.getDividerSize () * dividersCount;
            this.space = Math.max ( 0, multiSplitPane.getOrientation ().isHorizontal () ?
                    multiSplitPane.getWidth () - insets.left - insets.right - dividersSpace :
                    multiSplitPane.getHeight () - insets.top - insets.bottom - dividersSpace );

            // Total sizes
            int totalSizes = 0;
            double totalWeights = 0.0;
            int nonZeroViews = 0;
            double nonZeroWeights = 0.0;
            for ( final MultiSplitView view : views )
            {
                final MultiSplitViewState viewState = view.state ();
                final int size = viewState.size ();

                // Total size
                totalSizes += size;

                // Total weight
                totalWeights += view.constraints ().weight ();

                // Stats for non-zero size views
                if ( size > 0 )
                {
                    // Count
                    nonZeroViews++;

                    // Non-zero weights
                    nonZeroWeights += view.constraints ().weight ();
                }
            }
            this.totalSizes = totalSizes;
            this.totalWeights = totalWeights;
            this.nonZeroViews = nonZeroViews;
            this.nonZeroViewsWeights = nonZeroWeights;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy