package de.sciss.fscape.gui; import java.awt.*; /** * F*cking BorderLayout has all relevant fields private, so * we essential have to duplicate all functionality. */ public class MarginBorderLayout implements LayoutManager2 { private Insets margin; private int hGap; private int vGap; Component north; Component west; Component east; Component south; Component center; Component firstLine; Component lastLine; Component firstItem; Component lastItem; public static final String NORTH = "North"; public static final String SOUTH = "South"; public static final String EAST = "East"; public static final String WEST = "West"; public static final String CENTER = "Center"; public static final String BEFORE_FIRST_LINE = "First"; public static final String AFTER_LAST_LINE = "Last"; public static final String BEFORE_LINE_BEGINS = "Before"; public static final String AFTER_LINE_ENDS = "After"; public static final String PAGE_START = BEFORE_FIRST_LINE; public static final String PAGE_END = AFTER_LAST_LINE; public static final String LINE_START = BEFORE_LINE_BEGINS; public static final String LINE_END = AFTER_LINE_ENDS; public MarginBorderLayout() { this(0, 0); } public MarginBorderLayout(int hGap, int vGap) { this(hGap, vGap, new Insets(0, 0, 0, 0)); } public MarginBorderLayout(Insets margin) { this(0, 0, margin); } public MarginBorderLayout(int hGap, int vGap, Insets margin) { this.hGap = hGap; this.vGap = vGap; this.margin = (Insets) margin.clone(); } public int getHgap() { return hGap; } public void setHgap(int hGap) { this.hGap = hGap; } public int getVgap() { return vGap; } public void setVgap(int vGap) { this.vGap = vGap; } public Insets getMargin() { return (Insets) margin.clone(); } public void setMargin(Insets margin) { this.margin.left = margin.left; this.margin.top = margin.top; this.margin.right = margin.right; this.margin.bottom = margin.bottom; } @Override public Dimension minimumLayoutSize(Container target) { synchronized (target.getTreeLock()) { Dimension dim = new Dimension(0, 0); boolean ltr = target.getComponentOrientation().isLeftToRight(); Component c = null; if ((c=getChild(EAST,ltr)) != null) { Dimension d = c.getMinimumSize(); dim.width += d.width + hGap; dim.height = Math.max(d.height, dim.height); } if ((c=getChild(WEST,ltr)) != null) { Dimension d = c.getMinimumSize(); dim.width += d.width + hGap; dim.height = Math.max(d.height, dim.height); } if ((c=getChild(CENTER,ltr)) != null) { Dimension d = c.getMinimumSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if ((c=getChild(NORTH,ltr)) != null) { Dimension d = c.getMinimumSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height + vGap; } if ((c=getChild(SOUTH,ltr)) != null) { Dimension d = c.getMinimumSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height + vGap; } Insets insets = target.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; dim.width += margin.left + margin.right; dim.height += margin.top + margin.bottom; return dim; } } @Override public Dimension preferredLayoutSize(Container target) { synchronized (target.getTreeLock()) { Dimension dim = new Dimension(0, 0); boolean ltr = target.getComponentOrientation().isLeftToRight(); Component c = null; if ((c=getChild(EAST,ltr)) != null) { Dimension d = c.getPreferredSize(); dim.width += d.width + hGap; dim.height = Math.max(d.height, dim.height); } if ((c=getChild(WEST,ltr)) != null) { Dimension d = c.getPreferredSize(); dim.width += d.width + hGap; dim.height = Math.max(d.height, dim.height); } if ((c=getChild(CENTER,ltr)) != null) { Dimension d = c.getPreferredSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if ((c=getChild(NORTH,ltr)) != null) { Dimension d = c.getPreferredSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height + vGap; } if ((c=getChild(SOUTH,ltr)) != null) { Dimension d = c.getPreferredSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height + vGap; } Insets insets = target.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; dim.width += margin.left + margin.right; dim.height += margin.top + margin.bottom; return dim; } } public Dimension maximumLayoutSize(Container target) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } public float getLayoutAlignmentX(Container parent) { return 0.5f; } public float getLayoutAlignmentY(Container parent) { return 0.5f; } public void invalidateLayout(Container target) {} private Component getChild(String key, boolean ltr) { Component result = null; if (key.equals(NORTH)) { result = (firstLine != null) ? firstLine : north; } else if (key.equals(SOUTH)) { result = (lastLine != null) ? lastLine : south; } else if (key.equals(WEST)) { result = ltr ? firstItem : lastItem; if (result == null) { result = west; } } else if (key.equals(EAST)) { result = ltr ? lastItem : firstItem; if (result == null) { result = east; } } else if (key.equals(CENTER)) { result = center; } if (result != null && !result.isVisible()) { result = null; } return result; } public void addLayoutComponent(Component comp, Object constraints) { synchronized (comp.getTreeLock()) { if ((constraints == null) || (constraints instanceof String)) { addLayoutComponent((String)constraints, comp); } else { throw new IllegalArgumentException("cannot add to layout: constraint must be a string (or null)"); } } } @Deprecated public void addLayoutComponent(String name, Component comp) { synchronized (comp.getTreeLock()) { /* Special case: treat null the same as "Center". */ if (name == null) { name = "Center"; } /* Assign the component to one of the known regions of the layout. */ if ("Center".equals(name)) { center = comp; } else if ("North".equals(name)) { north = comp; } else if ("South".equals(name)) { south = comp; } else if ("East".equals(name)) { east = comp; } else if ("West".equals(name)) { west = comp; } else if (BEFORE_FIRST_LINE.equals(name)) { firstLine = comp; } else if (AFTER_LAST_LINE.equals(name)) { lastLine = comp; } else if (BEFORE_LINE_BEGINS.equals(name)) { firstItem = comp; } else if (AFTER_LINE_ENDS.equals(name)) { lastItem = comp; } else { throw new IllegalArgumentException("cannot add to layout: unknown constraint: " + name); } } } public void removeLayoutComponent(Component comp) { synchronized (comp.getTreeLock()) { if (comp == center) { center = null; } else if (comp == north) { north = null; } else if (comp == south) { south = null; } else if (comp == east) { east = null; } else if (comp == west) { west = null; } if (comp == firstLine) { firstLine = null; } else if (comp == lastLine) { lastLine = null; } else if (comp == firstItem) { firstItem = null; } else if (comp == lastItem) { lastItem = null; } } } public Component getLayoutComponent(Object constraints) { if (CENTER.equals(constraints)) { return center; } else if (NORTH.equals(constraints)) { return north; } else if (SOUTH.equals(constraints)) { return south; } else if (WEST.equals(constraints)) { return west; } else if (EAST.equals(constraints)) { return east; } else if (PAGE_START.equals(constraints)) { return firstLine; } else if (PAGE_END.equals(constraints)) { return lastLine; } else if (LINE_START.equals(constraints)) { return firstItem; } else if (LINE_END.equals(constraints)) { return lastItem; } else { throw new IllegalArgumentException("cannot get component: unknown constraint: " + constraints); } } public Component getLayoutComponent(Container target, Object constraints) { boolean ltr = target.getComponentOrientation().isLeftToRight(); Component result = null; if (NORTH.equals(constraints)) { result = (firstLine != null) ? firstLine : north; } else if (SOUTH.equals(constraints)) { result = (lastLine != null) ? lastLine : south; } else if (WEST.equals(constraints)) { result = ltr ? firstItem : lastItem; if (result == null) { result = west; } } else if (EAST.equals(constraints)) { result = ltr ? lastItem : firstItem; if (result == null) { result = east; } } else if (CENTER.equals(constraints)) { result = center; } else { throw new IllegalArgumentException("cannot get component: invalid constraint: " + constraints); } return result; } public Object getConstraints(Component comp) { //fix for 6242148 : API method java.awt.BorderLayout.getConstraints(null) should return null if (comp == null){ return null; } if (comp == center) { return CENTER; } else if (comp == north) { return NORTH; } else if (comp == south) { return SOUTH; } else if (comp == west) { return WEST; } else if (comp == east) { return EAST; } else if (comp == firstLine) { return PAGE_START; } else if (comp == lastLine) { return PAGE_END; } else if (comp == firstItem) { return LINE_START; } else if (comp == lastItem) { return LINE_END; } return null; } @Override public void layoutContainer(Container target) { synchronized (target.getTreeLock()) { Insets insets = target.getInsets(); int top = insets.top + margin.top; int bottom = target.getHeight() - (insets.bottom + margin.bottom); int left = insets.left + margin.left; int right = target.getWidth() - (insets.right + margin.right); boolean ltr = target.getComponentOrientation().isLeftToRight(); Component c = null; if ((c=getChild(NORTH,ltr)) != null) { c.setSize(right - left, c.getHeight()); Dimension d = c.getPreferredSize(); c.setBounds(left, top, right - left, d.height); top += d.height + vGap; } if ((c=getChild(SOUTH,ltr)) != null) { c.setSize(right - left, c.getHeight()); Dimension d = c.getPreferredSize(); c.setBounds(left, bottom - d.height, right - left, d.height); bottom -= d.height + vGap; } if ((c=getChild(EAST,ltr)) != null) { c.setSize(c.getWidth(), bottom - top); Dimension d = c.getPreferredSize(); c.setBounds(right - d.width, top, d.width, bottom - top); right -= d.width + hGap; } if ((c=getChild(WEST,ltr)) != null) { c.setSize(c.getWidth(), bottom - top); Dimension d = c.getPreferredSize(); c.setBounds(left, top, d.width, bottom - top); left += d.width + hGap; } if ((c=getChild(CENTER,ltr)) != null) { c.setBounds(left, top, right - left, bottom - top); } } } public String toString() { return getClass().getName() + "[hGap=" + hGap + ",vGap=" + vGap + ",margin=" + margin + "]"; } }