Files
samskivert/src/java/com/samskivert/swing/GroupLayout.java
T
ray 30ae1be3c8 Patch from Charlie Groves:
- Makes the button arg on GroupLayout.makeButtonBox a vararg so multiple
  buttons can be passed in at creation time.  It also adds a version using
  center justification as the default since that's what we do about 80%
  of the time in yohoho.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@2337 6335cc39-0255-0410-8fd6-9bcaacd3b74c
2008-07-18 18:30:04 +00:00

491 lines
13 KiB
Java

//
// $Id$
//
// samskivert library - useful routines for java programs
// Copyright (C) 2001-2007 Michael Bayne
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.swing;
import java.awt.*;
import javax.swing.JComponent;
import javax.swing.JPanel;
import java.util.HashMap;
/**
* Group layout managers lay out widgets in horizontal or vertical groups.
*/
public abstract class GroupLayout
implements LayoutManager2
{
/**
* The group layout managers supports two constraints: fixedness
* and weight. A fixed component will not be stretched along the major
* axis of the group. Those components that are stretched will have
* the extra space divided among them according to their weight
* (specifically receiving the ratio of their weight to the total
* weight of all of the free components in the container).
*
* To add a component with the fixed constraints, use the FIXED constant.
*/
public static class Constraints
{
/**
* Constructs a new constraints object with the specified weight,
* which is only applicable with the STRETCH policy.
*/
public Constraints (int weight)
{
_weight = weight;
}
/**
* Is this Constraints specifying fixed?
*/
public final boolean isFixed ()
{
return (this == FIXED);
}
/**
* Get the weight.
*/
public final int getWeight ()
{
return _weight;
}
/**
* The weight of this component relative to the other components
* in the container. Only valid if the layout policy is STRETCH.
*/
protected int _weight = 1;
}
/** A class used to make our policy constants type-safe. */
public static class Policy
{
int code;
public Policy (int code)
{
this.code = code;
}
}
/** A class used to make our policy constants type-safe. */
public static class Justification
{
int code;
public Justification (int code)
{
this.code = code;
}
}
/**
* A constraints object that indicates that the component should be
* fixed and have the default weight of one. This is so commonly used
* that we create and make this object available here.
*/
public final static Constraints FIXED = new Constraints(Integer.MIN_VALUE);
/**
* Do not adjust the widgets on this axis.
*/
public final static Policy NONE = new Policy(0);
/**
* Stretch all the widgets to their maximum possible size on this
* axis.
*/
public final static Policy STRETCH = new Policy(1);
/**
* Stretch all the widgets to be equal to the size of the largest
* widget on this axis.
*/
public final static Policy EQUALIZE = new Policy(2);
/**
* Only valid for off-axis policy, this leaves widgets alone unless
* they are larger in the off-axis direction than their container, in
* which case it constrains them to fit on the off-axis.
*/
public final static Policy CONSTRAIN = new Policy(3);
/** A justification constant. */
public final static Justification CENTER = new Justification(0);
/** A justification constant. */
public final static Justification LEFT = new Justification(1);
/** A justification constant. */
public final static Justification RIGHT = new Justification(2);
/** A justification constant. */
public final static Justification TOP = new Justification(3);
/** A justification constant. */
public final static Justification BOTTOM = new Justification(4);
/** The default gap between components, in pixels. */
public static final int DEFAULT_GAP = 5;
public void setPolicy (Policy policy)
{
_policy = policy;
}
public Policy getPolicy ()
{
return _policy;
}
public void setOffAxisPolicy (Policy offpolicy)
{
_offpolicy = offpolicy;
}
public Policy getOffAxisPolicy ()
{
return _offpolicy;
}
public void setGap (int gap)
{
_gap = gap;
}
public int getGap ()
{
return _gap;
}
public void setJustification (Justification justification)
{
_justification = justification;
}
public Justification getJustification ()
{
return _justification;
}
public void setOffAxisJustification (Justification justification)
{
_offjust = justification;
}
public Justification getOffAxisJustification ()
{
return _offjust;
}
public void addLayoutComponent (String name, Component comp)
{
// nothing to do here
}
public void removeLayoutComponent (Component comp)
{
if (_constraints != null) {
_constraints.remove(comp);
}
}
public void addLayoutComponent (Component comp, Object constraints)
{
if (constraints != null) {
if (constraints instanceof Constraints) {
if (_constraints == null) {
_constraints = new HashMap<Component,Constraints>();
}
_constraints.put(comp, (Constraints)constraints);
} else {
throw new RuntimeException("GroupLayout constraints " +
"object must be of type " +
"GroupLayout.Constraints");
}
}
}
public float getLayoutAlignmentX (Container target)
{
// we don't support alignment like this
return 0f;
}
public float getLayoutAlignmentY (Container target)
{
// we don't support alignment like this
return 0f;
}
public Dimension minimumLayoutSize (Container parent)
{
return getLayoutSize(parent, MINIMUM);
}
public Dimension preferredLayoutSize (Container parent)
{
return getLayoutSize(parent, PREFERRED);
}
public Dimension maximumLayoutSize (Container parent)
{
return getLayoutSize(parent, MAXIMUM);
}
protected abstract Dimension getLayoutSize (Container parent, int type);
public abstract void layoutContainer (Container parent);
public void invalidateLayout (Container target)
{
// nothing to do here
}
/**
* Get the Constraints for the specified child component.
*
* @return a Constraints object, never null.
*/
protected Constraints getConstraints (Component child)
{
if (_constraints != null) {
Constraints c = _constraints.get(child);
if (c != null) {
return c;
}
}
return DEFAULT_CONSTRAINTS;
}
/**
* Computes dimensions of the children widgets that are useful for the
* group layout managers.
*/
protected DimenInfo computeDimens (Container parent, int type)
{
int count = parent.getComponentCount();
DimenInfo info = new DimenInfo();
info.dimens = new Dimension[count];
for (int i = 0; i < count; i++) {
Component child = parent.getComponent(i);
if (!child.isVisible()) {
continue;
}
Dimension csize;
switch (type) {
case MINIMUM:
csize = child.getMinimumSize();
break;
case MAXIMUM:
csize = child.getMaximumSize();
break;
default:
csize = child.getPreferredSize();
break;
}
info.count++;
info.totwid += csize.width;
info.tothei += csize.height;
if (csize.width > info.maxwid) {
info.maxwid = csize.width;
}
if (csize.height > info.maxhei) {
info.maxhei = csize.height;
}
Constraints c = getConstraints(child);
if (c.isFixed()) {
info.fixwid += csize.width;
info.fixhei += csize.height;
info.numfix++;
} else {
info.totweight += c.getWeight();
if (csize.width > info.maxfreewid) {
info.maxfreewid = csize.width;
}
if (csize.height > info.maxfreehei) {
info.maxfreehei = csize.height;
}
}
info.dimens[i] = csize;
}
return info;
}
/**
* Creates a {@link JPanel} that is configured with a center-justified {@link HGroupLayout}
* with a configuration conducive to containing a row of buttons. Any supplied buttons are
* added to the box.
*/
public static JPanel makeButtonBox (JComponent... buttons)
{
return makeButtonBox(GroupLayout.CENTER, buttons);
}
/**
* Creates a {@link JPanel} that is configured with an {@link HGroupLayout} with a
* configuration conducive to containing a row of buttons. Any supplied buttons are added to
* the box.
*/
public static JPanel makeButtonBox (Justification justification, JComponent... buttons)
{
JPanel box = new JPanel(new HGroupLayout(NONE, justification));
for (JComponent button : buttons) {
box.add(button);
box.setOpaque(false);
}
return box;
}
/**
* Creates a {@link JPanel} that is configured with an {@link
* HGroupLayout} with the default configuration.
*/
public static JPanel makeHBox ()
{
return new JPanel(new HGroupLayout());
}
/**
* Creates a {@link JPanel} that is configured with an {@link
* HGroupLayout} with a configuration that stretches in both
* directions, with the specified gap.
*/
public static JPanel makeHStretchBox (int gap)
{
return new JPanel(new HGroupLayout(STRETCH, STRETCH, gap, CENTER));
}
/**
* Creates a {@link JPanel} that is configured with an {@link
* HGroupLayout} with the specified on-axis policy (default
* configuration otherwise).
*/
public static JPanel makeHBox (Policy policy)
{
return new JPanel(new HGroupLayout(policy));
}
/**
* Creates a {@link JPanel} that is configured with an {@link
* HGroupLayout} with the specified on-axis policy and justification
* (default configuration otherwise).
*/
public static JPanel makeHBox (Policy policy, Justification justification)
{
return new JPanel(new HGroupLayout(policy, justification));
}
/**
* Creates a {@link JPanel} that is configured with an {@link
* HGroupLayout} with the specified on-axis policy, justification and
* off-axis policy (default configuration otherwise).
*/
public static JPanel makeHBox (Policy policy, Justification justification,
Policy offAxisPolicy)
{
return new JPanel(new HGroupLayout(policy, offAxisPolicy,
DEFAULT_GAP, justification));
}
/**
* Creates a {@link JPanel} that is configured with an {@link
* VGroupLayout} with the default configuration.
*/
public static JPanel makeVBox ()
{
return new JPanel(new VGroupLayout());
}
/**
* Creates a {@link JPanel} that is configured with an {@link
* VGroupLayout} with the specified on-axis policy (default
* configuration otherwise).
*/
public static JPanel makeVBox (Policy policy)
{
return new JPanel(new VGroupLayout(policy));
}
/**
* Creates a {@link JPanel} that is configured with an {@link
* VGroupLayout} with the specified on-axis policy and justification
* (default configuration otherwise).
*/
public static JPanel makeVBox (Policy policy, Justification justification)
{
return new JPanel(new VGroupLayout(policy, justification));
}
/**
* Creates a {@link JPanel} that is configured with an {@link
* VGroupLayout} with the specified on-axis policy, justification and
* off-axis policy (default configuration otherwise).
*/
public static JPanel makeVBox (Policy policy, Justification justification,
Policy offAxisPolicy)
{
return new JPanel(new VGroupLayout(policy, offAxisPolicy,
DEFAULT_GAP, justification));
}
/**
* Creates a {@link JPanel} that is configured with an {@link
* VGroupLayout} with a configuration that stretches in both
* directions, with the specified gap.
*/
public static JPanel makeVStretchBox (int gap)
{
return new JPanel(new VGroupLayout(STRETCH, STRETCH, gap, CENTER));
}
protected Policy _policy = NONE;
protected Policy _offpolicy = CONSTRAIN;
protected int _gap = DEFAULT_GAP;
protected Justification _justification = CENTER;
protected Justification _offjust = CENTER;
protected HashMap<Component,Constraints> _constraints;
protected static final int MINIMUM = 0;
protected static final int PREFERRED = 1;
protected static final int MAXIMUM = 2;
/** All children added without a Constraints object are
* constrained by this Constraints object. */
protected static final Constraints DEFAULT_CONSTRAINTS = new Constraints(1);
}