SWT BorderLayout v2
続き。リファクタリングして、spacing(AWTのBorderLayoutでいうところのhgap, vgap)を指定できるようにした。
LayoutDataとしてStringというかBorderLayout.CENTERみたいに書きたかったのでその辺は変更なし。
以下例によってソース丸ごと。次はFlowLayoutかな。
package net.dotinterface.layout; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Layout; // TODO margin support public class BorderLayout extends Layout { public static final String NORTH = "NORTH"; public static final String WEST = "WEST"; public static final String CENTER = "CENTER"; public static final String EAST = "EAST"; public static final String SOUTH = "SOUTH"; public int horizontalSpacing; public int verticalSpacing; public BorderLayout() { this(0, 0); } public BorderLayout(int horizontalSpacing, int verticalSpacing) { this.horizontalSpacing = horizontalSpacing; this.verticalSpacing = verticalSpacing; } private static class Border { final String name; Control ctrl; Point size = new Point(0, 0); Border(String name) { this.name = name; } } private static class Borders { final Border north = new Border(NORTH); final Border west = new Border(WEST); final Border center = new Border(CENTER); final Border east = new Border(EAST); final Border south = new Border(SOUTH); final Border items = { north, west, center, east, south }; } protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { Borders borders = borders(composite); return new Point(computeMaxWidth(borders), computeMaxHeight(borders)); } private Borders borders(Composite composite) { Borders borders = new Borders(); Control children = composite.getChildren(); for (int i = 0; i < children.length; i++) { Control c = children[i]; Object data = c.getLayoutData(); String bs = data instanceof String ? (String) data : CENTER; for (int j = 0; j < borders.items.length; j++) { Border b = borders.items[j]; if (bs.equals(b.name)) { if (c.isVisible()) { b.ctrl = c; b.size = c.computeSize(SWT.DEFAULT, SWT.DEFAULT); } else { b.ctrl = null; } break; } } } return borders; } private int computeMaxWidth(Borders borders) { boolean west = borders.west.ctrl != null; boolean center = borders.center.ctrl != null; boolean east = borders.east.ctrl != null; int nw = borders.north.size.x; int ww = borders.west.size.x; int cw = borders.center.size.x; int ew = borders.east.size.x; int sw = borders.south.size.x; if (west && center) { cw += horizontalSpacing; } if (center && east) { cw += horizontalSpacing; } return Math.max(Math.max(nw, ww + cw + ew), sw); } private int computeMaxHeight(Borders borders) { boolean north = borders.north.ctrl != null; boolean west = borders.west.ctrl != null; boolean center = borders.center.ctrl != null; boolean east = borders.east.ctrl != null; boolean south = borders.south.ctrl != null; int nh = borders.north.size.y; int wh = borders.west.size.y; int ch = borders.center.size.y; int eh = borders.east.size.y; int sh = borders.south.size.y; if (north && west) { wh += verticalSpacing; } if (west && south) { wh += verticalSpacing; } if (north && center) { ch += verticalSpacing; } if (center && south) { ch += verticalSpacing; } if (north && east) { eh += verticalSpacing; } if (east && south) { eh += verticalSpacing; } return nh + Math.max(Math.max(wh, ch), eh) + sh; } protected void layout(Composite composite, boolean flushCache) { Rectangle ps = composite.getClientArea(); int pw = ps.width, ph = ps.height; int cx = 0, cy = 0, cw = pw, ch = ph; Borders borders = borders(composite); Control nc = borders.north.ctrl; Control sc = borders.south.ctrl; Control wc = borders.west.ctrl; Control ec = borders.east.ctrl; Control cc = borders.center.ctrl; if (nc != null) { // NORTH int nh = borders.north.size.y; nc.setBounds(0, 0, cw, nh); if (cc != null || sc != null) { nh += verticalSpacing; } cy += nh; ch -= nh; } if (sc != null) { // SOUTH int sh = borders.south.size.y; sc.setBounds(0, ph - sh, cw, sh); if (cc != null) { sh += verticalSpacing; } ch -= sh; } if (wc != null) { // WEST int ww = borders.west.size.x; wc.setBounds(0, cy, ww, ch); if (cc != null || ec != null) { ww += horizontalSpacing; } cx += ww; cw -= ww; } if (ec != null) { // EAST int ew = borders.east.size.x; ec.setBounds(pw - ew, cy, ew, ch); if (cc != null) { ew += horizontalSpacing; } cw -= ew; } if (cc != null) { // CENTER cc.setBounds(cx, cy, cw, ch); } } }