SWT BorderLayout

久しぶりに趣味コーディング。SWTにAWTと同じようなBorderLayoutがほしかったので実装してみた。
割と動いてる模様。だけど微妙にコントロール同士がかぶる。計算ミスかな〜。テスト用にコントロール矩形だけ描画するCanvas作って入れて試してみたら、意図通り動作していた。ButtonとかでSWT.BORDERスタイルを設定した時にコントロール領域をはみだすだけっぽい。
ってかソース丸ごと貼り付けるなよ>俺

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.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

public class BorderLayout extends Layout {
	public static final String CENTER = "CENTER";

	public static final String NORTH = "NORTH";

	public static final String WEST = "WEST";

	public static final String EAST = "EAST";

	public static final String SOUTH = "SOUTH";

	protected Point computeSize(Composite composite, int wHint, int hHint,
			boolean flushCache) {
		// TODO should cache preffered sizes of children
		Point cs = null, ns = null, ws = null, es = null, ss = null;
		Control controls = composite.getChildren();
		for (int i = 0; i < controls.length; i++) {
			Point size = controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
			Object o = controls[i].getLayoutData();
			if (o instanceof String) {
				String direction = (String) o;
				if (NORTH.equals(direction)) {
					ns = size;
				} else if (WEST.equals(direction)) {
					ws = size;
				} else if (EAST.equals(direction)) {
					es = size;
				} else if (SOUTH.equals(direction)) {
					ss = size;
				} else {
					cs = size;
				}
			} else {
				cs = size;
			}
		}
		int nw = ns == null ? 0 : ns.x;
		int ww = ws == null ? 0 : ws.x;
		int cw = cs == null ? 0 : cs.x;
		int ew = es == null ? 0 : es.x;
		int sw = ss == null ? 0 : ss.x;
		int mw = Math.max(Math.max(nw, ww + cw + ew), sw);

		int nh = ns == null ? 0 : ns.y;
		int wh = ws == null ? 0 : ws.y;
		int ch = cs == null ? 0 : cs.y;
		int eh = es == null ? 0 : es.y;
		int sh = ss == null ? 0 : ss.y;
		int mh = nh + Math.max(Math.max(wh, ch), eh) + sh;

		return new Point(mw, mh);
	}

	protected void layout(Composite composite, boolean flushCache) {
		Rectangle parentSize = composite.getClientArea();
		int pw = parentSize.width;
		int ph = parentSize.height;

		// TODO should cache preffered sizes of children
		Control cc = null, nc = null, wc = null, ec = null, sc = null;
		Control controls = composite.getChildren();
		for (int i = 0; i < controls.length; i++) {
			Object o = controls[i].getLayoutData();
			if (o instanceof String) {
				String direction = (String) o;
				if (NORTH.equals(direction)) {
					if (nc != null) {
						nc.setVisible(false);
					}
					nc = controls[i];
				} else if (WEST.equals(direction)) {
					if (wc != null) {
						wc.setVisible(false);
					}
					wc = controls[i];
				} else if (EAST.equals(direction)) {
					if (ec != null) {
						ec.setVisible(false);
					}
					ec = controls[i];
				} else if (SOUTH.equals(direction)) {
					if (sc != null) {
						sc.setVisible(false);
					}
					sc = controls[i];
				} else {
					if (cc != null) {
						cc.setVisible(false);
					}
					cc = controls[i];
				}
			} else {
				if (cc != null) {
					cc.setVisible(false);
				}
				cc = controls[i];
			}
		}

		int cx = 0, cy = 0, cw = pw, ch = ph;
		if (nc != null) { // NORTH
			nc.setVisible(true);
			Point size = nc.computeSize(pw, SWT.DEFAULT);
			nc.setBounds*1;

		Text tc = new Text(s, SWT.BORDER);
		tc.setText("Center");
		tc.setLayoutData(BorderLayout.CENTER);

		Button bw = new Button(s, SWT.BORDER);
		bw.setText("West");
		bw.setLayoutData(BorderLayout.WEST);

		Button be = new Button(s, SWT.NONE);
		be.setText("East");
		be.setLayoutData(BorderLayout.EAST);

		Button be2 = new Button(s, SWT.NONE);
		be2.setText("East2");
		be2.setLayoutData(BorderLayout.EAST);

		Label ls = new Label(s, SWT.BORDER);
		ls.setText("South");
		ls.setLayoutData(BorderLayout.SOUTH);

		ToolBar tbn = new ToolBar(s, SWT.NONE);
		ToolItem ti;
		for (int i = 0; i < 5; i++) {
			ti = new ToolItem(tbn, SWT.NONE);
			ti.setText("North" + (i + 1));
		}
		tbn.setLayoutData(BorderLayout.NORTH);

		s.open();
		while (!s.isDisposed()) {
			if (!d.readAndDispatch()) {
				d.sleep();
			}
		}
		d.dispose();
	}
}

*1:pw - size.x) / 2, 0, size.x, size.y); cy += size.y; ch -= size.y; } if (sc != null) { // SOUTH sc.setVisible(true); Point size = sc.computeSize(pw, SWT.DEFAULT); sc.setBounds((pw - size.x) / 2, ph - size.y, size.x, size.y); ch -= size.y; } if (wc != null) { // WEST wc.setVisible(true); Point size = wc.computeSize(SWT.DEFAULT, ch); wc.setBounds(0, cy + (ch - size.y) / 2, size.x, size.y); cx += size.x; cw -= size.x; } if (ec != null) { // EAST ec.setVisible(true); Point size = ec.computeSize(SWT.DEFAULT, ch); ec.setBounds(pw - size.x, cy + (ch - size.y) / 2, size.x, size.y); cw -= size.x; } if (cc != null) { // CENTER cc.setVisible(true); cc.setBounds(cx, cy, cw, ch); } } public static void main(String[] args) { Display d = new Display(); Shell s = new Shell(d); s.setText("BorderLayout Test"); s.setLayout(new BorderLayout(