001/*
002 * $Id$
003 *
004 * Copyright 2009 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 * 
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015 * Lesser General Public License for more details.
016 * 
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020 *
021 */
022package org.jdesktop.swingx;
023
024import javax.swing.JComponent;
025import javax.swing.JViewport;
026import javax.swing.SwingConstants;
027
028import org.jdesktop.swingx.util.Contract;
029
030/**
031 * Sizing hints for layout, useful f.i. in a Scrollable implementation.<p>
032 * 
033 * Inspired by <a href=
034 * http://tips4java.wordpress.com/2009/12/20/scrollable-panel/> Rob Camick</a>.
035 * <p>
036 * PENDING JW: naming... suggestions?<br>
037 * KS: I'd go with TrackingHint or ScrollableTrackingHint, since it is used in getScrollableTracksViewportXXX.
038 * 
039 * 
040 * @author Jeanette Winzenburg
041 * @author Karl Schaefer
042 */
043public enum ScrollableSizeHint {
044    /**
045     * Size should be unchanged.
046     */
047    NONE {
048        /**
049         * {@inheritDoc}
050         */
051        @Override
052        boolean getTracksParentSizeImpl(JComponent component, int orientation) {
053            return false;
054        }
055    }, 
056    
057    /**
058     * Size should be adjusted to parent size. 
059     */
060    FIT {
061        /**
062         * {@inheritDoc}
063         */
064        @Override
065        boolean getTracksParentSizeImpl(JComponent component, int orientation) {
066            return true;
067        }
068    }, 
069    
070    /**
071     * Stretches the component when its parent is larger than its minimum size.
072     */
073    MINIMUM_STRETCH {
074        /**
075         * {@inheritDoc}
076         */
077        @Override
078        boolean getTracksParentSizeImpl(JComponent component, int orientation) {
079            switch (orientation) {
080            case SwingConstants.HORIZONTAL:
081                return component.getParent() instanceof JViewport
082                        && component.getParent().getWidth() > component.getMinimumSize().width
083                        && component.getParent().getWidth() < component.getMaximumSize().width;
084            case SwingConstants.VERTICAL:
085                return component.getParent() instanceof JViewport
086                        && component.getParent().getHeight() > component.getMinimumSize().height
087                        && component.getParent().getHeight() < component.getMaximumSize().height;
088            default:
089                throw new IllegalArgumentException("invalid orientation");
090            }
091        }
092    },
093    
094    /**
095     * Stretches the component when its parent is larger than its preferred size.
096     */
097    PREFERRED_STRETCH {
098        /**
099         * {@inheritDoc}
100         */
101        @Override
102        boolean getTracksParentSizeImpl(JComponent component, int orientation) {
103            switch (orientation) {
104            case SwingConstants.HORIZONTAL:
105                return component.getParent() instanceof JViewport
106                        && component.getParent().getWidth() > component.getPreferredSize().width
107                        && component.getParent().getWidth() < component.getMaximumSize().width;
108            case SwingConstants.VERTICAL:
109                return component.getParent() instanceof JViewport
110                        && component.getParent().getHeight() > component.getPreferredSize().height
111                        && component.getParent().getHeight() < component.getMaximumSize().height;
112            default:
113                throw new IllegalArgumentException("invalid orientation");
114            }
115        }
116    },
117    
118    /**
119     * Width should be stretched to parent width if smaller, unchanged otherwise.
120     */
121    @Deprecated
122    HORIZONTAL_STRETCH {
123        /**
124         * {@inheritDoc}
125         * <p>
126         * Returns {@code false}.
127         */
128        @Override
129        @Deprecated
130        public boolean isVerticalCompatible() {
131            return false;
132        }
133        
134        /**
135         * {@inheritDoc}
136         */
137        @Override
138        boolean getTracksParentSizeImpl(JComponent component, int orientation) {
139            if (orientation != SwingConstants.HORIZONTAL) {
140                throw new IllegalArgumentException();
141            }
142            
143            if (component.getParent() != null) {
144                return component.getParent().getWidth() > component.getPreferredSize().width
145                    && component.getParent().getWidth() < component.getMaximumSize().width;
146            }
147
148            return false;
149        }
150    },
151    
152    /**
153     * Width should be stretched to parent height if smaller, unchanged otherwise.
154     */
155    @Deprecated
156    VERTICAL_STRETCH {
157        /**
158         * {@inheritDoc}
159         * <p>
160         * Returns {@code false}.
161         */
162        @Override
163        @Deprecated
164        public boolean isHorizontalCompatible() {
165            return false;
166        }
167        
168        /**
169         * {@inheritDoc}
170         */
171        @Override
172        boolean getTracksParentSizeImpl(JComponent component, int orientation) {
173            if (orientation != SwingConstants.VERTICAL) {
174                throw new IllegalArgumentException();
175            }
176            
177            if (component.getParent() != null) {
178                return component.getParent().getHeight() > component.getPreferredSize().height
179                        && component.getParent().getWidth() < component.getMaximumSize().height;
180            }
181
182            return false;
183        }
184    };
185    
186    /**
187     * Returns a boolean indicating whether the component's size should be
188     * adjusted to parent.
189     *  
190     * @param component the component resize, must not be null
191     * @return a boolean indicating whether the component's size should be
192     *    adjusted to parent
193     *    
194     * @throws NullPointerException if component is null   
195     */
196    @Deprecated
197    public boolean getTracksParentSize(JComponent component) {
198        return getTracksParentSize(component, 0);
199    }
200    
201    /**
202     * Returns a boolean indicating whether the component's size should be
203     * adjusted to parent.
204     *  
205     * @param component the component resize, must not be null
206     * @return a boolean indicating whether the component's size should be
207     *    adjusted to parent
208     *    
209     * @throws NullPointerException if component is null
210     * @throws IllegalArgumentException if orientation is invalid
211     */
212    public boolean getTracksParentSize(JComponent component, int orientation) {
213        Contract.asNotNull(component, "component must be not-null");
214        
215        return getTracksParentSizeImpl(component, orientation);
216    }
217
218    /**
219     * Returns a boolean indicating whether the hint can be used in 
220     * horizontal orientation.
221     * 
222     * @return a boolean indicating whether the hint can be used in horizontal
223     *   orientation. 
224     */
225    @Deprecated
226    public boolean isHorizontalCompatible() {
227        return true;
228    }
229    
230    /**
231     * Returns a boolean indicating whether the hint can be used in 
232     * vertical orientation.
233     * 
234     * @return a boolean indicating whether the hint can be used in vertical
235     *   orientation. 
236     */
237    @Deprecated
238    public boolean isVerticalCompatible() {
239        return true;
240    }
241
242    /**
243     * Determines whether the supplied component is smaller than its parent; used to determine
244     * whether to track with the parents size.
245     * 
246     * @param component
247     *            the component to test
248     * @param orientation
249     *            the orientation to test
250     * @return {@code true} to track; {@code false} otherwise
251     */
252    abstract boolean getTracksParentSizeImpl(JComponent component, int orientation);
253}