Place components at exact locations (x, y, width, height) and then determine how they behave when the window containing them (their parent) is resized
import java.awt.*;
import java.util.*;
/*
* @(#)FunLayout.java 1.0 96/10/12 Eric Swildens Copyright (c) 1996
*
* Permission to use, copy, modify, and distribute this software
* for any purpose is hereby granted provided that this copyright
* notice appears in all copies.
*
* NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE ARE GIVEN, EITHER EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*/
public class FunLayout implements LayoutManager
{
// Using this layout manager, you can place components at exact
// locations (x, y, width, height) and then determine how they
// behave when the window containing them (their parent) is resized.
//
// sample use:
//
// fun1.html:
//
// <title>fun1 example</title>
// <applet code="fun1.class" width=400 height=300> </applet>
//
// fun1.java:
//
// import java.applet.Applet;
// import java.awt.*;
//
// public class fun1 extends Applet
// {
// public void init()
// {
// FunLayout layout = new FunLayout();
// setLayout(layout);
//
// setBackground(Color.lightGray);
//
// Button rightButton1 = new Button("Button1");
// rightButton1.reshape(300, 5, 90, 20);
// add(rightButton1);
// layout.movesRight(rightButton1);
//
// Button rightButton2 = new Button("Button 2");
// rightButton2.reshape(200, 5, 90, 20);
// add(rightButton2);
// layout.movesRight(rightButton2);
//
// Panel midPanel = new Panel();
// midPanel.reshape(5, 40, 390, 200);
// midPanel.setBackground(Color.blue);
// layout.widthChanges(midPanel);
// layout.heightChanges(midPanel);
// add(midPanel);
//
// Panel statusBar = new Panel();
// statusBar.reshape(5, 245, 390, 20);
// statusBar.setBackground(Color.black);
// layout.movesDown(statusBar);
// layout.widthChanges(statusBar);
// add(statusBar);
// }
// }
//
// The above code creates an applet containing 2 buttons, a center panel
// and a status panel. The two buttons are placed next to each other
// in the upper right. When the window is sized wider, the buttons
// will move to the right to stick near the edge of the window.
//
// The midPanel is placed in the center and when the window is sized
// larger (in both dimensions), the panel will grow wider and taller.
//
// The statusBar is placed on the bottom and sticks to the bottom of
// the panel when it is sized larger or smaller in height (it moves
// down if the window it is contained in is sized to a larger height).
// It will grow wider if the window it is contained in is sized wider.
//
// The advantage of the FunLayout is that you place components where you
// want them to appear (best when using an interface builder) and still
// have control over what happens during sizing.
//
// This is the default layout mechanism many interface systems use, such
// as Netscape's IFC. In fact, if you use this layout manager, you will
// find porting your code to Netscape's IFC much easier, as the layout
// container here is very similar to Netscape's IFC layout mechanism.
//
// There are only 4 methods which determine how components are resized
//
// layout.movesRight(comp);
// layout.movesDown(comp);
// layout.widthChanges(comp);
// layout.heightChanges(comp);
//
// When you determine which to choose, you should ask "What should the
// component do when the window is sized larger?"
//
// If you don't call any of the above methods for a component, it will
// simply stay at its current location.
//
// It's more Fun than a Bag of layouts :-)
//
private Hashtable _moves;
private Hashtable _negSized;
private Dimension _prevContainerSize;
private final static int MOVES_RIGHT = 2;
private final static int MOVES_DOWN = 4;
private final static int HEIGHT_CHANGES = 8;
private final static int WIDTH_CHANGES = 16;
public FunLayout()
{
_moves = new Hashtable();
_negSized = new Hashtable();
}
private int _getMove(Component comp)
{
if (!_moves.containsKey(comp))
return 0;
return ((Integer)_moves.get(comp)).intValue();
}
//
// private methods
//
private void _setMove(Component comp, int move)
{
if (_moves.containsKey(comp))
{
move |= ((Integer)_moves.get(comp)).intValue();
_moves.remove(comp);
}
_moves.put(comp, new Integer(move));
}
//
// LayoutManager implementation
//
public void addLayoutComponent(String name, Component c)
{
}
/**
* When the window containing the given component is stretched to a
* larger height, the given component will grow taller (and shorter
* when the window is shortened).
* @param comp the target Component
*/
public void heightChanges(Component comp)
{
if ((_getMove(comp) & MOVES_DOWN) > 0)
System.out.println(getClass() + ":layout conflict for " + comp);
_setMove(comp, HEIGHT_CHANGES);
}
public void layoutContainer(Container con)
{
int i, count, deltax, deltay, move;
Dimension conSize;
Rectangle rect;
Component comp;
conSize = con.getSize();
if (_prevContainerSize == null)
{
_prevContainerSize = conSize;
return;
}
deltax = conSize.width - _prevContainerSize.width;
deltay = conSize.height - _prevContainerSize.height;
_prevContainerSize = conSize;
count = con.countComponents();
for (i = 0; i < count; i++)
{
comp = con.getComponent(i);
if (!comp.isVisible())
continue;
move = _getMove(comp);
if (move == 0)
continue;
rect = comp.getBounds();
if (_negSized.containsKey(comp))
{
// the component is really at a negative size
rect = (Rectangle)_negSized.get(comp);
_negSized.remove(comp);
}
if ((move & MOVES_RIGHT) > 0)
rect.x += deltax;
else if ((move & WIDTH_CHANGES) > 0)
rect.width += deltax;
if ((move & MOVES_DOWN) > 0)
rect.y += deltay;
else if ((move & HEIGHT_CHANGES) > 0)
rect.height += deltay;
// if a components size becomes negative, we track it since the AWT
// does not allow components to have a size < (0, 0)
if (rect.width < 0 || rect.height < 0)
_negSized.put(comp, rect);
comp.setBounds(rect.x, rect.y, rect.width, rect.height);
}
}
public Dimension minimumLayoutSize(Container target)
{
return new Dimension(10, 10);
}
/**
* When the window containing the given component is stretched to a
* larger height, the given component will move down (and up
* when the window is shortened).
* @param comp the target Component
*/
public void movesDown(Component comp)
{
if ((_getMove(comp) & HEIGHT_CHANGES) > 0)
System.out.println(getClass() + ":layout conflict for " + comp);
_setMove(comp, MOVES_DOWN);
}
//
// public methods
//
/**
* When the window containing the given component is widened, the
* component will move right (and left when the window is shrunk).
* @param comp the target Component
*/
public void movesRight(Component comp)
{
if ((_getMove(comp) & WIDTH_CHANGES) > 0)
System.out.println(getClass() + ":layout conflict for " + comp);
_setMove(comp, MOVES_RIGHT);
}
public Dimension preferredLayoutSize(Container con)
{
Component comp;
Rectangle rect;
int i, count;
Dimension d;
d = new Dimension(0, 0);
count = con.countComponents();
for (i = 0; i < count; i++)
{
comp = con.getComponent(i);
if (!comp.isVisible())
continue;
rect = comp.getBounds();
if (d.width < rect.x + rect.width)
d.width = rect.x + rect.width;
if (d.height < rect.y + rect.height)
d.height = rect.y + rect.height;
}
return d;
}
public void removeLayoutComponent(Component c)
{
if (_negSized.containsKey(c))
_negSized.remove(c);
}
/**
* When the window containing the given component is widened, the
* component will grow wider (and smaller when the window is shrunk).
* @param comp the target Component
*/
public void widthChanges(Component comp)
{
if ((_getMove(comp) & MOVES_RIGHT) > 0)
System.out.println(getClass() + ":layout conflict for " + comp);
_setMove(comp, WIDTH_CHANGES);
}
}
Related examples in the same category