summaryrefslogtreecommitdiffstats
path: root/examples/org.eclipse.swt.examples.launcher/src/org/eclipse/swt/examples/launcher/SplitLayout.java
blob: 6637af1e07e84b321b5d70306112380054590502 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.examples.launcher;

 
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;

/**
 * A Layout class that automatically switches from a horizontal split to a vertical
 * split layout to accomodate changing size conditions.
 * 
 * Later on we might improve this class to take into account the "preferred" size of
 * the widgets.
 */
public class SplitLayout extends Layout {
	private static final int
		splitHorizontally = 0,
		splitVertically = 1;
	private int splitDirection = splitHorizontally;

	public int spacing = 3;
	public int marginTop = 3;
	public int marginLeft = 3;
	public int marginRight = 3;
	public int marginBottom = 3;

	/**
	 * Creates a new layout
	 */
	public SplitLayout() {
	}

	/**
	 * @see Layout#computeSize(Composite, int, int, boolean)
	 */
	protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
		if (wHint == SWT.DEFAULT) {
			if (hHint == SWT.DEFAULT) {
				Point hSplitSize = computeHSplitSize(composite, wHint, hHint, flushCache);
				Point vSplitSize = computeVSplitSize(composite, wHint, hHint, false);
				int hSplitArea = hSplitSize.x * hSplitSize.y;
				int vSplitArea = vSplitSize.x * vSplitSize.y;
				// Choose direction consuming least area
				if (hSplitArea < vSplitArea) {
					splitDirection = splitHorizontally;
					return hSplitSize;
				} else {
					splitDirection = splitVertically;
					return vSplitSize;
				}
			} else {
				// Constrained in height: split vertically
				splitDirection = splitVertically;
				return computeVSplitSize(composite, wHint, hHint, flushCache);
			}
		} else {
			if (hHint == SWT.DEFAULT) {
				// Constrained in width: split horizontally
				splitDirection = splitHorizontally;
				return computeHSplitSize(composite, wHint, hHint, flushCache);
			} else {
				if (hHint < wHint) {
					splitDirection = splitVertically;
					return computeVSplitSize(composite, wHint, hHint, flushCache);
				} else {
					splitDirection = splitHorizontally;
					return computeHSplitSize(composite, wHint, hHint, flushCache);
				}					
			}
		}
	}
	/**
	 * @see Layout#layout(Composite, boolean)
	 */
	protected void layout(Composite composite, boolean flushCache) {
		Rectangle clientArea = composite.getClientArea();
		computeSize(composite, clientArea.width, clientArea.height, false);
		
		Control[] children = composite.getChildren();
		clientArea.x += marginLeft;
		clientArea.y += marginTop;
		clientArea.width -= marginRight + marginLeft;
		clientArea.height -= marginBottom + marginTop;
		Point position = new Point(clientArea.x, clientArea.y);

		for (int i = 0; i < children.length; ++i) {
			final Control child = children[i];
			final Rectangle bounds;
			if (splitDirection == splitHorizontally) {
				int height = clientArea.height / children.length;
				bounds = new Rectangle(position.x, position.y, clientArea.width, height);
				position.y += height + spacing;
			} else {
				int width = clientArea.width / children.length;
				bounds = new Rectangle(position.x, position.y, width, clientArea.height);
				position.x += width + spacing;
			}
			bounds.width = Math.max(bounds.width, 0);
			bounds.height = Math.max(bounds.height, 0);
			child.setBounds(bounds);
		}
	}

	private Point computeHSplitSize(Composite composite, int wHint, int hHint, boolean flushCache) {
		Point size = new Point(marginLeft + marginRight, marginTop + marginBottom);
		Control[] children = composite.getChildren();
		for (int i = 0; i < children.length; ++i) {
			final Control child = children[i];

			Point childSize = child.computeSize(wHint, hHint, flushCache);
			size.x = Math.max(size.x, childSize.x);
			size.y += childSize.y + spacing;
		}
		return size;
	}

	private Point computeVSplitSize(Composite composite, int wHint, int hHint, boolean flushCache) {
		Point size = new Point(marginLeft + marginRight, marginTop + marginBottom);
		Control[] children = composite.getChildren();
		for (int i = 0; i < children.length; ++i) {
			final Control child = children[i];

			Point childSize = child.computeSize(wHint, hHint, flushCache);
			size.x += childSize.x + spacing;
			size.y = Math.max(size.y, childSize.y);
		}
		return size;
	}
}