Java tutorial
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); } }