/*
 * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package javax.swing;

import java.awt.Container;
import javax.swing.plaf.ComponentUI;
import sun.awt.AppContext;

/**
 * <code>LayoutStyle</code> provides information about how to position
 * components.  This class is primarily useful for visual tools and
 * layout managers.  Most developers will not need to use this class.
 * <p>
 * You typically don't set or create a
 * <code>LayoutStyle</code>.  Instead use the static method
 * <code>getInstance</code> to obtain the current instance.
 *
 * @since 1.6
 */
public abstract class LayoutStyle {
    /**
     * Sets the shared instance of <code>LayoutStyle</code>.  Specifying
     * <code>null</code> results in using the <code>LayoutStyle</code> from
     * the current <code>LookAndFeel</code>.
     *
     * @param style the <code>LayoutStyle</code>, or <code>null</code>
     * @see #getInstance
     */
    public static void setInstance(LayoutStyle style) {
        synchronized(LayoutStyle.class) {
            if (style == null) {
                AppContext.getAppContext().remove(LayoutStyle.class);
            }
            else {
                AppContext.getAppContext().put(LayoutStyle.class, style);
            }
        }
    }

    /**
     * Returns the shared instance of <code>LayoutStyle</code>.  If an instance
     * has not been specified in <code>setInstance</code>, this will return
     * the <code>LayoutStyle</code> from the current <code>LookAndFeel</code>.
     *
     * @see LookAndFeel#getLayoutStyle
     * @return the shared instance of <code>LayoutStyle</code>
     */
    public static LayoutStyle getInstance() {
        LayoutStyle style;
        synchronized(LayoutStyle.class) {
            style = (LayoutStyle)AppContext.getAppContext().
                    get(LayoutStyle.class);
        }
        if (style == null) {
            return UIManager.getLookAndFeel().getLayoutStyle();
        }
        return style;
    }


    /**
     * <code>ComponentPlacement</code> is an enumeration of the
     * possible ways two components can be placed relative to each
     * other.  <code>ComponentPlacement</code> is used by the
     * <code>LayoutStyle</code> method <code>getPreferredGap</code>.  Refer to
     * <code>LayoutStyle</code> for more information.
     *
     * @see LayoutStyle#getPreferredGap(JComponent,JComponent,
     *      ComponentPlacement,int,Container)
     * @since 1.6
     */
    public enum ComponentPlacement {
        /**
         * Enumeration value indicating the two components are
         * visually related and will be placed in the same parent.
         * For example, a <code>JLabel</code> providing a label for a
         * <code>JTextField</code> is typically visually associated
         * with the <code>JTextField</code>; the constant <code>RELATED</code>
         * is used for this.
         */
        RELATED,

        /**
         * Enumeration value indicating the two components are
         * visually unrelated and will be placed in the same parent.
         * For example, groupings of components are usually visually
         * separated; the constant <code>UNRELATED</code> is used for this.
         */
        UNRELATED,

        /**
         * Enumeration value indicating the distance to indent a component
         * is being requested.  For example, often times the children of
         * a label will be horizontally indented from the label.  To determine
         * the preferred distance for such a gap use the
         * <code>INDENT</code> type.
         * <p>
         * This value is typically only useful with a direction of
         * <code>EAST</code> or <code>WEST</code>.
         */
        INDENT;
    }


    /**
     * Creates a new <code>LayoutStyle</code>.  You generally don't
     * create a <code>LayoutStyle</code>.  Instead use the method
     * <code>getInstance</code> to obtain the current
     * <code>LayoutStyle</code>.
     */
    public LayoutStyle() {
    }

    /**
     * Returns the amount of space to use between two components.
     * The return value indicates the distance to place
     * <code>component2</code> relative to <code>component1</code>.
     * For example, the following returns the amount of space to place
     * between <code>component2</code> and <code>component1</code>
     * when <code>component2</code> is placed vertically above
     * <code>component1</code>:
     * <pre>
     *   int gap = getPreferredGap(component1, component2,
     *                             ComponentPlacement.RELATED,
     *                             SwingConstants.NORTH, parent);
     * </pre>
     * The <code>type</code> parameter indicates the relation between
     * the two components.  If the two components will be contained in
     * the same parent and are showing similar logically related
     * items, use <code>RELATED</code>.  If the two components will be
     * contained in the same parent but show logically unrelated items
     * use <code>UNRELATED</code>.  Some look and feels may not
     * distinguish between the <code>RELATED</code> and
     * <code>UNRELATED</code> types.
     * <p>
     * The return value is not intended to take into account the
     * current size and position of <code>component2</code> or
     * <code>component1</code>.  The return value may take into
     * consideration various properties of the components.  For
     * example, the space may vary based on font size, or the preferred
     * size of the component.
     *
     * @param component1 the <code>JComponent</code>
     *               <code>component2</code> is being placed relative to
     * @param component2 the <code>JComponent</code> being placed
     * @param position the position <code>component2</code> is being placed
     *        relative to <code>component1</code>; one of
     *        <code>SwingConstants.NORTH</code>,
     *        <code>SwingConstants.SOUTH</code>,
     *        <code>SwingConstants.EAST</code> or
     *        <code>SwingConstants.WEST</code>
     * @param type how the two components are being placed
     * @param parent the parent of <code>component2</code>; this may differ
     *        from the actual parent and it may be <code>null</code>
     * @return the amount of space to place between the two components
     * @throws NullPointerException if <code>component1</code>,
     *         <code>component2</code> or <code>type</code> is
     *         <code>null</code>
     * @throws IllegalArgumentException if <code>position</code> is not
     *         one of <code>SwingConstants.NORTH</code>,
     *         <code>SwingConstants.SOUTH</code>,
     *         <code>SwingConstants.EAST</code> or
     *         <code>SwingConstants.WEST</code>
     * @see LookAndFeel#getLayoutStyle
     * @since 1.6
     */
    public abstract int getPreferredGap(JComponent component1,
                                        JComponent component2,
                                        ComponentPlacement type, int position,
                                        Container parent);

    /**
     * Returns the amount of space to place between the component and specified
     * edge of its parent.
     *
     * @param component the <code>JComponent</code> being positioned
     * @param position the position <code>component</code> is being placed
     *        relative to its parent; one of
     *        <code>SwingConstants.NORTH</code>,
     *        <code>SwingConstants.SOUTH</code>,
     *        <code>SwingConstants.EAST</code> or
     *        <code>SwingConstants.WEST</code>
     * @param parent the parent of <code>component</code>; this may differ
     *        from the actual parent and may be <code>null</code>
     * @return the amount of space to place between the component and specified
     *         edge
     * @throws IllegalArgumentException if <code>position</code> is not
     *         one of <code>SwingConstants.NORTH</code>,
     *         <code>SwingConstants.SOUTH</code>,
     *         <code>SwingConstants.EAST</code> or
     *         <code>SwingConstants.WEST</code>
     */
    public abstract int getContainerGap(JComponent component, int position,
                                        Container parent);
}
