/* * @(#) PnutsLayout.java 1.2 98/05/12 * * Copyright (c) 1997,1998 Sun Microsystems, Inc. All Rights Reserved. * * This routine is taken from the PNUTS package at: * http://javacenter.sun.co.jp/pnuts/index.html * * See the file "license.txt" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ package jas.util.layout; // package name changed for use with JAS import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.LayoutManager2; import java.awt.Point; import java.awt.Rectangle; import java.util.BitSet; import java.util.Enumeration; import java.util.Hashtable; import java.util.StringTokenizer; /** * The PnutsLayout is a general purpose geometry manager. * It is more user-friendly than any LayoutManager out there * and as flexible as GridBagLayout. * e.g. * <pre> * setLayout(new PnutsLayout("cols = 3")); * add(button1, "ipadx = 20, ipady = 20"); * add(button2, "padx = 20, pady = 20"); * add(button3, "colspan = 2"); * add(button4, "rowspan = 2"); * add(button3, "halign = left, valign = top"); * add(button3, "halign = right, valign = bottom"); * add(button3, "halign = center, valign = fill"); * </pre> * * <table border> * <tr><th>property</th><th>the meaning</th><th>default</th></tr> * <tr><td>cols</td><td>number of columns</td><td>1</td></tr> * <tr><td>uniform</td><td>if width and/or height of each columns are all same, "x", "y" or "xy"</td><td>""</td></tr> * <tr><td>colspan</td><td>number of columns the component occupies</td><td>1</td></tr> * <tr><td>rowspan</td><td>number of rows the component occupies</td><td>1</td></tr> * <tr><td>padx</td><td>external padding (x)</td><td>0</td></tr> * <tr><td>pady</td><td>external padding (y)</td><td>0</td></tr> * <tr><td>ipadx</td><td>internal padding (x)</td><td>0</td></tr> * <tr><td>ipady</td><td>internal padding (y)</td><td>0</td></tr> * <tr><td>halign</td><td>alignment of x. One of "left", "right", "center", "fill"</td><td>center</td></tr> * <tr><td>valign</td><td>alignment of y. One of "top", "bottom", "center", "fill"</td><td>center</td></tr> * <tr><td>expand</td><td>expand as the size of container changes. one of "x", "y", "xy"</td><td>""</td></tr> * </table> * * <p> * @version 1.2 * @autor Toyokazu Tomatsu */ public class PnutsLayout implements LayoutManager2, java.io.Serializable { public static final int CENTER = 0; public static final int TOP = 1; public static final int BOTTOM = 2; public static final int LEFT = 4; public static final int RIGHT = 8; public static final int V_FIT = 16; public static final int H_FIT = 32; static final int V_FILL = TOP | BOTTOM; static final int H_FILL = LEFT | RIGHT; static Integer[] integer = new Integer[33]; static { for (int i = 0; i < integer.length; i++){ integer[i] = new Integer(i); } } static Integer getInteger(int i){ if (i < 32){ return integer[i]; } else { return new Integer(i); } } static int zero[] = new int[16]; static { for (int i = 0; i < zero.length; i++){ zero[i] = 0; } } /** * alignment table */ Hashtable alignmentTable = new Hashtable(); /** * span table */ Hashtable spanTable = new Hashtable(); /** * padx/y table */ Hashtable padTable = new Hashtable(); /** * ipadx/y table */ Hashtable iPadTable = new Hashtable(); private int widths[]; private int heights[]; private int hfit[]; private int vfit[]; private int hfits; private int vfits; int grid_x[]; int grid_y[]; int pos_x[] = new int[8]; int pos_y[] = new int[8]; private Dimension psize; private boolean valid = false; /** * default align */ protected int align = CENTER; /** * default padx */ protected int padx; /** * default pady */ protected int pady; /** * default ipadx */ protected int ipadx; /** * default ipady */ protected int ipady; /** * The number of columns */ protected int cols; /** * The number of rows */ protected int rows; protected boolean xfix; protected boolean yfix; /** * construct a PnutsLayout */ public PnutsLayout() { this(1); } /** * construct a PnutsLayout with specified number of columns * @param cols the number of columns */ public PnutsLayout(int cols) { this(cols, 0, 0); } /** * construct a PnutsLayout * @param cols the number of columns * @param padx default external padding * @param pady default external padding */ public PnutsLayout(int cols, int padx, int pady) { this.cols = cols; this.padx = padx; this.pady = pady; } /* * construct a PnutsLayout from a constraint string. * Usage: * "cols=<number>, padx=<number>, pady=<number>, uniform=<x | y | xy>" * * @param str a constraint string */ public PnutsLayout(String str) { Hashtable t = str2table(str); this.cols = getInt(t.get("cols"), 1); this.padx = getInt(t.get("padx"), 0); this.pady = getInt(t.get("pady"), 0); this.ipadx = getInt(t.get("ipadx"), 0); this.ipady = getInt(t.get("ipady"), 0); int ha = 0; int va = 0; String h = (String)t.get("halign"); if (h != null){ if ("left".equalsIgnoreCase(h)){ ha |= LEFT; } else if ("right".equalsIgnoreCase(h)){ ha |= RIGHT; } else if ("center".equalsIgnoreCase(h)){ ha |= CENTER; } else if ("fill".equalsIgnoreCase(h)){ ha |= RIGHT; ha |= LEFT; } } else { ha = this.align & (LEFT | RIGHT | H_FIT); } String v = (String)t.get("valign"); if (v != null){ if ("top".equalsIgnoreCase(v)){ va |= TOP; } else if ("bottom".equalsIgnoreCase(v)){ va |= BOTTOM; } else if ("center".equalsIgnoreCase(v)){ va |= CENTER; } else if ("fill".equalsIgnoreCase(v)){ va |= TOP; va |= BOTTOM; } } else { va = this.align & (TOP | BOTTOM | V_FIT); } String ex = (String)t.get("expand"); if (ex instanceof String){ if ("x".equalsIgnoreCase(ex)){ ha |= H_FIT; } else if ("y".equalsIgnoreCase(ex)){ va |= V_FIT; } else if ("xy".equalsIgnoreCase(ex)){ ha |= H_FIT; va |= V_FIT; } } this.align = ha | va; String fix = (String)t.get("uniform"); if ("x".equals(fix)){ xfix = true; } else if ("y".equals(fix)){ yfix = true; } else if ("xy".equals(fix)){ xfix = true; yfix = true; } } /** * Adds the specified component to the layout, using the specified * constraint object. * @param comp the component to be added. * @param obj an object that determines how * the component is added to the layout. * Usage: * container.add(component, new Object[]{align, colspan, rowspan}); */ public void addLayoutComponent(Component comp, Object obj) { if (obj instanceof Hashtable){ setConstraints(comp, (Hashtable)obj); } else if (obj instanceof String){ setConstraints(comp, (String)obj); } } /** * Specify layout constraints with comma-separated list of * "<property>=<value>". * * halign ::= left | right | center | fill * valign ::= top | bottom | center | fill * expand ::= x | y | xy * * @param comp the component * @param str a string that describes how * the component is added to the layout. */ public void setConstraints(Component comp, String str){ int hal = this.align & (LEFT | RIGHT | H_FIT); int val = this.align & (TOP | BOTTOM | V_FIT); Hashtable tab = str2table(str); Object v0 = tab.get("expand"); if (v0 instanceof String){ String s = (String)v0; if ("x".equalsIgnoreCase(s)){ hal |= H_FIT; } else if ("y".equalsIgnoreCase(s)){ val |= V_FIT; } else if ("xy".equalsIgnoreCase(s)){ hal |= H_FIT; val |= V_FIT; } } Object v1 = tab.get("halign"); if (v1 instanceof String){ hal &= ~(LEFT | RIGHT); String s = (String)v1; if ("left".equalsIgnoreCase(s)){ hal |= LEFT; } else if ("right".equalsIgnoreCase(s)){ hal |= RIGHT; } else if ("center".equalsIgnoreCase(s)){ hal |= CENTER; } else if ("fill".equalsIgnoreCase(s)){ hal |= RIGHT; hal |= LEFT; } } Object v2 = tab.get("valign"); if (v2 instanceof String){ val &= ~(TOP | BOTTOM); String s = (String)v2; if ("top".equalsIgnoreCase(s)){ val |= TOP; } else if ("bottom".equalsIgnoreCase(s)){ val |= BOTTOM; } else if ("center".equalsIgnoreCase(s)){ val |= CENTER; } else if ("fill".equalsIgnoreCase(s)){ val |= TOP; val |= BOTTOM; } } tab.put("valign", getInteger(val)); tab.put("halign", getInteger(hal)); setConstraints(comp, tab); } static int getInt(Object obj, int defaultValue){ if (obj == null){ return defaultValue; } if (obj instanceof Integer){ return ((Integer)obj).intValue(); } else { return Integer.parseInt((String)obj); } } /** * Specify layout constraints with Hashtable * * @param comp the component to be set the constraint. * @param table a Hashtable that describes how * the component is added to the layout. */ public void setConstraints(Component comp, Hashtable table){ int h = getInt(table.get("halign"), this.align & (LEFT | RIGHT)); int v = getInt(table.get("valign"), this.align & (TOP | BOTTOM)); alignmentTable.put(comp, getInteger(h | v)); int c = getInt(table.get("colspan"), 1); if (c <= cols){ spanTable.put(comp, new Object[]{ getInteger(c), getInteger(getInt(table.get("rowspan"), 1))}); } padTable.put(comp, new Object[]{ getInteger(getInt(table.get("padx"), this.padx)), getInteger(getInt(table.get("pady"), this.pady))}); iPadTable.put(comp, new Object[]{ getInteger(getInt(table.get("ipadx"), this.ipadx)), getInteger(getInt(table.get("ipady"), this.ipady))}); } /** * get a string representaion of constraint for the * specified component * * @param comp the component to be investigate * @return string representaion of the constraint */ public String getConstraintString(Component comp){ Hashtable tab = getConstraints(comp); StringBuffer buf = new StringBuffer(); String halign = (String)tab.get("halign"); if (halign != null){ buf.append("halign = " + halign); } String valign = (String)tab.get("valign"); if (valign != null){ if (buf.length() > 0) buf.append(", "); buf.append("valign = " + valign); } String expand = (String)tab.get("expand"); if (expand != null){ if (buf.length() > 0) buf.append(", "); buf.append("expand = " + expand); } int padx = ((Integer)tab.get("padx")).intValue(); if (padx > 0){ if (buf.length() > 0) buf.append(", "); buf.append("padx = " + padx); } int pady = ((Integer)tab.get("pady")).intValue(); if (pady > 0){ if (buf.length() > 0) buf.append(", "); buf.append("pady = " + pady); } int ipadx = ((Integer)tab.get("ipadx")).intValue(); if (ipadx > 0){ if (buf.length() > 0) buf.append(", "); buf.append("ipadx = " + ipadx); } int ipady = ((Integer)tab.get("ipady")).intValue(); if (ipady > 0){ if (buf.length() > 0) buf.append(", "); buf.append("ipady = " + ipady); } int colspan = ((Integer)tab.get("colspan")).intValue(); if (colspan > 1){ if (buf.length() > 0) buf.append(", "); buf.append("colspan = " + colspan); } int rowspan = ((Integer)tab.get("rowspan")).intValue(); if (rowspan > 1){ if (buf.length() > 0) buf.append(", "); buf.append("rowspan = " + rowspan); } return buf.toString(); } /** * get a Hashtable of constraint for the specified component * * @param comp the component to be investigate * @return the constraints as Hashtable */ public Hashtable getConstraints(Component comp){ Hashtable tab = new Hashtable(); Object o1 = alignmentTable.get(comp); int align = this.align; if (o1 != null){ align = ((Integer)o1).intValue(); String halign = "center"; String valign = "center"; switch (align & H_FILL){ case LEFT: halign = "left"; break; case RIGHT: halign = "right"; break; case H_FILL: halign = "fill"; break; } switch (align & V_FILL){ case TOP: valign = "top"; break; case BOTTOM: valign = "bottom"; break; case V_FILL: valign = "fill"; break; } if (!"center".equals(halign)){ tab.put("halign", halign); } if (!"center".equals(valign)){ tab.put("valign", valign); } String expand = ""; if ((align & H_FIT) == H_FIT){ expand += "x"; } if ((align & V_FIT) == V_FIT){ expand += "y"; } if (expand.length() > 0){ tab.put("expand", expand); } } Object[] o2 = (Object[])padTable.get(comp); if (o2 != null){ tab.put("padx", o2[0]); tab.put("pady", o2[1]); } Object o3[] = (Object[])iPadTable.get(comp); if (o3 != null){ tab.put("ipadx", o3[0]); tab.put("ipady", o3[1]); } Object o4[] = (Object[])spanTable.get(comp); if (o4 != null){ tab.put("colspan", o4[0]); tab.put("rowspan", o4[1]); } return tab; } /** * Adds the specified component with the specified name to * the layout. * @param name the component name * @param comp the component to be added */ public void addLayoutComponent(String name, Component comp){ } /** * Removes the specified component from the layout. * @param comp the component ot be removed */ public void removeLayoutComponent(Component comp){ } /** * Returns the maximum size of this component. * @see java.awt.Component#getMinimumSize() * @see java.awt.Component#getPreferredSize() * @see LayoutManager */ public Dimension maximumLayoutSize(Container target){ return target.getMaximumSize(); } /** * Returns the alignment along the x axis. This specifies how * the component would like to be aligned relative to other * components. The value should be a number between 0 and 1 * where 0 represents alignment along the origin, 1 is aligned * the furthest away from the origin, 0.5 is centered, etc. */ public float getLayoutAlignmentX(Container target){ return 0f; } /** * Returns the alignment along the y axis. This specifies how * the component would like to be aligned relative to other * components. The value should be a number between 0 and 1 * where 0 represents alignment along the origin, 1 is aligned * the furthest away from the origin, 0.5 is centered, etc. */ public float getLayoutAlignmentY(Container target){ return 0f; } /** * Invalidates the layout, indicating that if the layout manager * has cached information it should be discarded. * * @param target container to invalidate the layout */ public void invalidateLayout(Container target){ valid = false; } /** * Set the number of columns * * @param cols the number of columns */ public void setCols(int cols){ for (Enumeration e = spanTable.elements(); e.hasMoreElements(); ){ Object[] obj = (Object[])e.nextElement(); int colspan = ((Integer)obj[0]).intValue(); if (colspan > cols){ return; } } this.cols = cols; valid = false; } /** * set "uniform" property * * @param x uniform property for horizontal direction * @param y uniform property for vertical direction */ public void setUniform(boolean x, boolean y){ xfix = x; yfix = y; valid = false; } /** * get "uniform" property * * @return boolean array of "uniform property" */ public boolean[] getUniform(){ return new boolean[]{xfix, yfix}; } /** * @param comp the component of which you want to change colspan * @param colspan the number of columns the component occupies */ public void setColspan(Component comp, int colspan){ Object[] p = (Object[])spanTable.get(comp); if (p != null){ p[0] = getInteger(colspan); spanTable.put(comp, p); } else { spanTable.put(comp, new Object[]{ getInteger(colspan), getInteger(1)}); } invalidateLayout(comp.getParent()); } /** * @param comp the component of which you want to get colspan * @return the value of "colspan" property */ public int getColspan(Component comp){ Object o[] = (Object[])spanTable.get(comp); if (o == null || o.length < 2){ return 1; } else { return ((Integer)o[0]).intValue(); } } /** * @param comp the component of which you want to change rowspan * @param rowspan the number of rows the component occupies */ public void setRowspan(Component comp, int rowspan){ Object[] p = (Object[])spanTable.get(comp); if (p != null){ p[1] = getInteger(rowspan); spanTable.put(comp, p); } else { spanTable.put(comp, new Object[]{ getInteger(1), getInteger(rowspan)}); } invalidateLayout(comp.getParent()); } /** * @param comp the component of which you want to get rowspan * @return the value of "rowspan" property */ public int getRowspan(Component comp){ Object o[] = (Object[])spanTable.get(comp); if (o == null || o.length < 2){ return 1; } else { return ((Integer)o[1]).intValue(); } } /** * @param comp the component of which you want to change alignment * @param align "left", "right", "fill", "center" */ public void setHAlign(Component comp, String s){ int i = 0; if ("left".equalsIgnoreCase(s)){ i = LEFT; } else if ("right".equalsIgnoreCase(s)){ i = RIGHT; } else if ("fill".equalsIgnoreCase(s)){ i = H_FILL; } else { i = CENTER; } alignmentTable.put(comp, getInteger(i)); invalidateLayout(comp.getParent()); } /** * @param comp the component of which you want to change alignment * @param align "top", "bottom", "fill", "center" */ public void setVAlign(Component comp, String s){ int i = 0; if ("left".equalsIgnoreCase(s)){ i = TOP; } else if ("bottom".equalsIgnoreCase(s)){ i = BOTTOM; } else if ("fill".equalsIgnoreCase(s)){ i = V_FILL; } else { i = CENTER; } alignmentTable.put(comp, getInteger(i)); invalidateLayout(comp.getParent()); } /** * @param comp the component of which you want to get alignment * @return "fill" | "left" | "right" | "center" */ public String getHAlign(Component comp){ Integer it = (Integer)alignmentTable.get(comp); int i = this.align; if (it != null){ i = it.intValue(); } if ((i & H_FILL) == H_FILL){ return "fill"; } if ((i & LEFT) == LEFT){ return "left"; } if ((i & RIGHT) == RIGHT){ return "right"; } return "center"; } /** * @param comp the component of which you want to get alignment * @return "fill" | "top" | "bottom" | "center" */ public String getVAlign(Component comp){ Integer it = (Integer)alignmentTable.get(comp); int i = this.align; if (it != null){ i = it.intValue(); } if ((i & V_FILL) == V_FILL){ return "fill"; } if ((i & TOP) == TOP){ return "top"; } if ((i & BOTTOM) == BOTTOM){ return "bottom"; } return "center"; } /** * @param comp the component of which you want to set "expand" */ public void setExpand(Component comp, String ex){ Integer it = (Integer)alignmentTable.get(comp); int i = this.align; if (it != null){ i = it.intValue(); } if ("x".equalsIgnoreCase(ex)){ i |= H_FIT; } else if ("y".equalsIgnoreCase(ex)){ i |= V_FIT; } else if ("xy".equalsIgnoreCase(ex)){ i |= H_FIT; i |= V_FIT; } alignmentTable.put(comp, getInteger(i)); invalidateLayout(comp.getParent()); } /** * @param comp the component of which you want to get "expand" * @return "x" | "y" | "xy" | "" */ public String getExpand(Component comp){ Integer it = (Integer)alignmentTable.get(comp); int i = this.align; if (it != null){ i = it.intValue(); } if ((i & (H_FIT | V_FIT)) == (H_FIT | V_FIT)){ return "xy"; } if ((i & H_FIT) == H_FIT){ return "x"; } if ((i & V_FIT) == V_FIT){ return "y"; } return ""; } /** * @param comp the component of which you want to change alignment * @param x "padx" property * @param y "pady" property */ public void setPadding(Component comp, int x, int y){ padTable.put(comp, new Object[]{getInteger(x), getInteger(y)}); invalidateLayout(comp.getParent()); } /** * @param comp the component of which you want to get "padx" * @return the value of "padx" property */ public int getPadX(Component comp){ Object[] pair = (Object[])padTable.get(comp); if (pair != null){ return ((Integer)pair[0]).intValue(); } return 0; } /** * @param comp the component of which you want to get "pady" * @return the value of "pady" property */ public int getPadY(Component comp){ Object[] pair = (Object[])padTable.get(comp); if (pair != null){ return ((Integer)pair[1]).intValue(); } return 0; } /** * @param comp the component of which you want to change alignment * @param x "ipadx" property * @param y "ipady" property */ public void setIPadding(Component comp, int x, int y){ iPadTable.put(comp, new Object[]{getInteger(x), getInteger(y)}); invalidateLayout(comp.getParent()); } /** * @param comp the component of which you want to get "ipadx" * @return the value of "ipadx" property */ public int getIPadX(Component comp){ Object[] pair = (Object[])iPadTable.get(comp); if (pair != null){ return ((Integer)pair[0]).intValue(); } return 0; } /** * @param comp the component of which you want to get "ipady" * @return the value of "ipady" property */ public int getIPadY(Component comp){ Object[] pair = (Object[])iPadTable.get(comp); if (pair != null){ return ((Integer)pair[1]).intValue(); } return 0; } void clear(int[] array, int len){ int i = 0; for (; i <= len - zero.length; i += zero.length){ System.arraycopy(zero, 0, array, i, zero.length); } System.arraycopy(zero, 0, array, i, len - i); } void bindContainer(Container target){ if (valid){ return; } BitSet map[] = new BitSet[cols]; for (int i = 0; i < cols; i++){ map[i] = new BitSet(); } int nmembers = target.getComponentCount(); int _k = 0; int _j = 0; int _l = 0; if (pos_x.length < nmembers){ pos_x = new int[nmembers * 2]; } if (pos_y.length < nmembers){ pos_y = new int[nmembers * 2]; } clear(pos_x, nmembers); clear(pos_y, nmembers); for (int i = 0; i < nmembers; i++){ Component comp = target.getComponent(i); Object p[] = (Object[])spanTable.get(comp); int colspan = 1; int rowspan = 1; if (p != null){ colspan = ((Integer)p[0]).intValue(); rowspan = ((Integer)p[1]).intValue(); } while (!fit(_j, _k, colspan, rowspan, map)){ if (++_j >= cols){ _j = 0; ++_k; } } pos_y[i] = _k; pos_x[i] = _j; for (int jj = 0; jj < colspan; jj++){ for (int kk = 0; kk < rowspan; kk++){ map[_j + jj].set(_k + kk); } } if (_l < _k + rowspan){ _l = _k + rowspan; } if (++_j >= cols){ _j = 0; ++_k; } } rows = _l; grid_x = new int[cols + 1]; grid_y = new int[rows + 1]; widths = new int[cols]; heights = new int[rows]; vfit = new int[rows]; hfit = new int[cols]; int wmax = 0; int hmax = 0; for (int i = 0, j = 0, k = 0; i < nmembers; i++){ Component m = target.getComponent(i); Dimension d = m.getPreferredSize(); int d_width = d.width; int d_height = d.height; Object[] ip = (Object[])iPadTable.get(m); if (ip != null){ d_width = d.width + ((Integer)ip[0]).intValue(); d_height = d.height + ((Integer)ip[1]).intValue(); } Object pd[] = (Object[])padTable.get(m); int px = padx; int py = pady; if (pd != null){ px = ((Integer)pd[0]).intValue(); py = ((Integer)pd[1]).intValue(); } k = pos_y[i]; j = pos_x[i]; int colspan = 1; int rowspan = 1; Object p[] = (Object[])spanTable.get(m); if (p != null){ colspan = ((Integer)p[0]).intValue(); rowspan = ((Integer)p[1]).intValue(); } int wc = 0; for (int ii = 0; ii < colspan; ii++){ wc += widths[j + ii]; } if (wc < d_width + px * 2){ for (int ii = 0; ii < colspan; ii++){ widths[j + ii] += (d_width + px * 2 - wc) / colspan; if (xfix){ if (wmax < widths[j + ii]){ wmax = widths[j + ii]; } } } } if (heights[k] < (d_height + py * 2) / rowspan){ heights[k] = (d_height + py * 2) / rowspan; if (yfix){ if (hmax < heights[k]){ hmax = heights[k]; } } } Object val = alignmentTable.get(m); int al = this.align; if (val != null && val instanceof Integer){ al = ((Integer)val).intValue(); } if ((al & H_FIT) != 0){ for (int ii = 0; ii < colspan; ii++){ hfit[j + ii] |= 1; } } if ((al & V_FIT) != 0){ for (int ii = 0; ii < rowspan; ii++){ vfit[k + ii] |= 1; } } j += colspan; if (j >= cols){ j = 0; k++; } } if (xfix){ for (int _m = 0; _m < cols; _m++){ widths[_m] = wmax; // hfit[_m] = 1; } } if (yfix){ for (int _m = 0; _m < rows; _m++){ heights[_m] = hmax; // vfit[_m] = 1; } } int w = 0; int h = 0; for (int j = 0 ; j < cols ; j++) { w += widths[j]; } for (int j = 0 ; j < rows ; j++) { h += heights[j]; } hfits = 0; for (int i = 0; i < hfit.length; i++){ if ((hfit[i] & 1) != 0){ hfits++; } } vfits = 0; for (int i = 0; i < vfit.length; i++){ if ((vfit[i] & 1) != 0){ vfits++; } } Insets insets = target.getInsets(); w += insets.left + insets.right + padx * cols; h += insets.top + insets.bottom + pady * rows; psize = new Dimension(w, h); valid = true; } /** * Returns the preferred dimensions for this layout given the components * in the specified target container. * @param target the component which needs to be laid out * @see Container * @see #minimumLayoutSize */ public Dimension preferredLayoutSize(Container target) { bindContainer(target); return psize; } /** * Returns the minimum dimensions needed to layout the components * contained in the specified target container. * @param target the component which needs to be laid out * @see #preferredLayoutSize */ public Dimension minimumLayoutSize(Container target) { return preferredLayoutSize(target); } /** * Lays out the container. This method will actually reshape the * components in the target in order to satisfy the constraints of * the BorderLayout object. * @param target the specified component being laid out. * @see Container */ public void layoutContainer(Container target) { Insets insets = target.getInsets(); int nmembers = target.getComponentCount(); bindContainer(target); int tw = target.getSize().width; int th = target.getSize().height; int pw = psize.width; int ph = psize.height; int aw = 0; int ah = 0; if (hfits > 0){ aw = (tw - pw) / hfits; } if (vfits > 0){ ah = (th - ph) / vfits; } int h = insets.top; int w = insets.left; grid_x[0] = w; for (int i = 1; i <= cols; i++){ grid_x[i] = grid_x[i - 1] + widths[i - 1] + padx; if ((hfit[i - 1] & 1) != 0){ grid_x[i] += aw; } } grid_y[0] = h; for (int i = 1; i <= rows; i++){ grid_y[i] = grid_y[i - 1] + heights[i - 1] + pady; if ((vfit[i - 1] & 1) != 0){ grid_y[i] += ah; } } for (int i = 0, j = 0, k = 0; i < nmembers; i++){ Component m = target.getComponent(i); Dimension d = m.getPreferredSize(); int d_width = d.width; int d_height = d.height; Object[] ip = (Object[])iPadTable.get(m); if (ip != null){ d_width = d.width + ((Integer)ip[0]).intValue(); d_height = d.height + ((Integer)ip[1]).intValue(); } k = pos_y[i]; j = pos_x[i]; int colspan = 1; int rowspan = 1; Object p[] = (Object[])spanTable.get(m); if (p != null){ colspan = ((Integer)p[0]).intValue(); rowspan = ((Integer)p[1]).intValue(); } int al = this.align; Object val = alignmentTable.get(m); if (val != null && (val instanceof Integer)){ al = ((Integer)val).intValue(); } int x, y; int dw = d_width; int dh = d_height; Object pt[] = (Object[])padTable.get(m); int px = padx; int py = pady; if (pt != null){ px = ((Integer)pt[0]).intValue(); py = ((Integer)pt[1]).intValue(); } if ((al & LEFT) != 0){ x = grid_x[j] + px; // if ((al & RIGHT) != 0 && (al & H_FIT) != 0){ if ((al & RIGHT) != 0){ dw = grid_x[j + colspan] - grid_x[j] - px * 2; } } else if ((al & RIGHT) != 0){ x = grid_x[j + colspan] - dw - px; } else { x = (grid_x[j] + grid_x[j + colspan] - dw) / 2; } if ((al & TOP) != 0){ y = grid_y[k] + py; // if ((al & BOTTOM) != 0 && (al & V_FIT) != 0){ if ((al & BOTTOM) != 0){ dh = grid_y[k + rowspan] - grid_y[k] - py * 2; } } else if ((al & BOTTOM) != 0){ y = grid_y[k + rowspan] - dh - py; } else { y = (grid_y[k] + grid_y[k + rowspan] - dh) / 2; } m.setBounds(x, y, dw, dh); } } boolean fit(int x, int y, int c, int r, BitSet[] map){ for (int i = 0; i < c; i++){ for (int j = 0; j < r; j++){ if (x + i >= cols){ return false; } if (map[x + i].get(y + j)){ return false; } } } return true; } static Hashtable str2table(String str){ Hashtable table = new Hashtable(); StringTokenizer st = new StringTokenizer(str, ","); while (st.hasMoreTokens()){ String t = st.nextToken(); StringTokenizer st2 = new StringTokenizer(t, "= "); String key = st2.nextToken(); String value = st2.nextToken(); table.put(key, value); } return table; } /** * Get the number of columns * * @return the number of columns */ public int getCols(){ return cols; } /** * get the number of rows * * @return the number of rows */ public int getRows(){ if (!valid){ throw new RuntimeException("PnutsLayout not valid"); } return rows; } /** * get left-top point of the component(x,y) * * @param x the index of column * @param y the index of row * @return left-top point of the component */ public Point getGridPoint(Container target, int x, int y){ if (!valid){ return null; } return new Point(grid_x[x], grid_y[y]); } /** * get bounding-box for idx'th component * * @param idx the index of the component * @return bounding-box as Rectangle object */ public Rectangle getGridRectangle(Container target, int idx){ if (!valid){ return null; } int x = pos_x[idx]; int y = pos_y[idx]; int gx = grid_x[x]; int gy = grid_y[y]; Object s[] = (Object[])spanTable.get(target.getComponent(idx)); int sx = 1; int sy = 1; if (s != null){ sx = ((Integer)s[0]).intValue(); sy = ((Integer)s[1]).intValue(); } return new Rectangle(gx, gy, grid_x[x + sx] - gx, grid_y[y + sy] - gy); } /** * @return the String representation of this PnutsLayout's values. */ public String toString() { return getClass().getName() + "[cols=" + cols + ",padx=" + padx + ",pady=" + pady + ",ipadx=" + ipadx + ",ipady=" + ipady + "]"; } }