必须重写 SashForm 才能获得这种行为。 new SashForm(Composite parent, int style)
是旧行为;new SashForm(Composite parent, int style, false)
使用以像素为单位指定的宽度/高度。
未使用 SashForm 的两个以上 Composite 子项进行测试,如果您setLength
在使用新行为时不这样做,则会出现奇怪的行为,但不会破坏 SashForm 的现有用途
例如:
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
final SashForm form = new SashForm(shell, SWT.HORIZONTAL);
Button button = new Button(form, SWT.PUSH);
button.setText("Left");
Button buttonR = new Button(form, SWT.PUSH);
buttonR.setText("Right");
form.setLengths(new int[] { 250, 25 });
shell.pack();
shell.setSize(600, 400);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
第一个按钮将默认为 250 像素,第二个是其余的外壳
SashForm.java:
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
public class SashForm extends Composite {
/**
* The width of all sashes in the form.
*/
public int SASH_WIDTH = 3;
int sashStyle;
final private boolean weighted;
Sash[] sashes = new Sash[0];
// Remember background and foreground
// colors to determine whether to set
// sashes to the default color (null) or
// a specific color
Color background = null;
Color foreground = null;
Control[] controls = new Control[0];
Control maxControl = null;
Listener sashListener;
static final int DRAG_MINIMUM = 20;
public SashForm(Composite parent, int style) {
super(parent, checkStyle(style));
super.setLayout(new SashFormLayout());
sashStyle = ((style & SWT.VERTICAL) != 0) ? SWT.HORIZONTAL : SWT.VERTICAL;
if ((style & SWT.BORDER) != 0) sashStyle |= SWT.BORDER;
if ((style & SWT.SMOOTH) != 0) sashStyle |= SWT.SMOOTH;
sashListener = new Listener() {
public void handleEvent(Event e) {
onDragSash(e);
}
};
weighted = true;
}
public SashForm(Composite parent, int style, boolean weighted) {
super(parent, checkStyle(style));
super.setLayout(new SashFormLayout());
sashStyle = ((style & SWT.VERTICAL) != 0) ? SWT.HORIZONTAL : SWT.VERTICAL;
if ((style & SWT.BORDER) != 0) sashStyle |= SWT.BORDER;
if ((style & SWT.SMOOTH) != 0) sashStyle |= SWT.SMOOTH;
sashListener = new Listener() {
public void handleEvent(Event e) {
onDragSash(e);
}
};
this.weighted = weighted;
}
static int checkStyle (int style) {
int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
return style & mask;
}
Sash createSash() {
Sash sash = new Sash(this, sashStyle);
sash.setBackground(background);
sash.setForeground(foreground);
sash.setToolTipText(getToolTipText());
sash.addListener(SWT.Selection, sashListener);
return sash;
}
@Override
public int getOrientation() {
//checkWidget();
return (sashStyle & SWT.VERTICAL) != 0 ? SWT.HORIZONTAL : SWT.VERTICAL;
}
/**
* Returns the width of the sashes when the controls in the SashForm are
* laid out.
*
* @return the width of the sashes
*
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*
* @since 3.4
*/
public int getSashWidth() {
checkWidget();
return SASH_WIDTH;
}
@Override
public int getStyle() {
int style = super.getStyle();
style |= getOrientation() == SWT.VERTICAL ? SWT.VERTICAL : SWT.HORIZONTAL;
if ((sashStyle & SWT.SMOOTH) != 0) style |= SWT.SMOOTH;
return style;
}
/**
* Answer the control that currently is maximized in the SashForm.
* This value may be null.
*
* @return the control that currently is maximized or null
*/
public Control getMaximizedControl(){
//checkWidget();
return this.maxControl;
}
public int[] getWeights() {
checkWidget();
Control[] cArray = getControls(false);
int[] ratios = new int[cArray.length];
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
ratios[i] = (int)(((SashFormData)data).weight * 1000 >> 16);
} else {
ratios[i] = 200;
}
}
return ratios;
}
Control[] getControls(boolean onlyVisible) {
Control[] children = getChildren();
Control[] result = new Control[0];
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Sash) continue;
if (onlyVisible && !children[i].getVisible()) continue;
Control[] newResult = new Control[result.length + 1];
System.arraycopy(result, 0, newResult, 0, result.length);
newResult[result.length] = children[i];
result = newResult;
}
return result;
}
boolean getWeighted() {
return weighted;
}
void onDragSash(Event event) {
Sash sash = (Sash)event.widget;
int sashIndex = -1;
for (int i= 0; i < sashes.length; i++) {
if (sashes[i] == sash) {
sashIndex = i;
break;
}
}
if (sashIndex == -1) return;
Control c1 = controls[sashIndex];
Control c2 = controls[sashIndex + 1];
Rectangle b1 = c1.getBounds();
Rectangle b2 = c2.getBounds();
Rectangle sashBounds = sash.getBounds();
Rectangle area = getClientArea();
boolean correction = false;
if (getOrientation() == SWT.HORIZONTAL) {
correction = b1.width < DRAG_MINIMUM || b2.width < DRAG_MINIMUM;
int totalWidth = b2.x + b2.width - b1.x;
int shift = event.x - sashBounds.x;
b1.width += shift;
b2.x += shift;
b2.width -= shift;
if (b1.width < DRAG_MINIMUM) {
b1.width = DRAG_MINIMUM;
b2.x = b1.x + b1.width + sashBounds.width;
b2.width = totalWidth - b2.x;
event.x = b1.x + b1.width;
event.doit = false;
}
if (b2.width < DRAG_MINIMUM) {
b1.width = totalWidth - DRAG_MINIMUM - sashBounds.width;
b2.x = b1.x + b1.width + sashBounds.width;
b2.width = DRAG_MINIMUM;
event.x = b1.x + b1.width;
event.doit = false;
}
Object data1 = c1.getLayoutData();
if (data1 == null || !(data1 instanceof SashFormData)) {
data1 = new SashFormData();
c1.setLayoutData(data1);
}
Object data2 = c2.getLayoutData();
if (data2 == null || !(data2 instanceof SashFormData)) {
data2 = new SashFormData();
c2.setLayoutData(data2);
}
((SashFormData)data1).weight = (((long)b1.width << 16) + area.width - 1) / area.width;
((SashFormData)data1).length = b1.width;
((SashFormData)data2).weight = (((long)b2.width << 16) + area.width - 1) / area.width;
((SashFormData)data2).length = b2.width;
} else {
correction = b1.height < DRAG_MINIMUM || b2.height < DRAG_MINIMUM;
int totalHeight = b2.y + b2.height - b1.y;
int shift = event.y - sashBounds.y;
b1.height += shift;
b2.y += shift;
b2.height -= shift;
if (b1.height < DRAG_MINIMUM) {
b1.height = DRAG_MINIMUM;
b2.y = b1.y + b1.height + sashBounds.height;
b2.height = totalHeight - b2.y;
event.y = b1.y + b1.height;
event.doit = false;
}
if (b2.height < DRAG_MINIMUM) {
b1.height = totalHeight - DRAG_MINIMUM - sashBounds.height;
b2.y = b1.y + b1.height + sashBounds.height;
b2.height = DRAG_MINIMUM;
event.y = b1.y + b1.height;
event.doit = false;
}
Object data1 = c1.getLayoutData();
if (data1 == null || !(data1 instanceof SashFormData)) {
data1 = new SashFormData();
c1.setLayoutData(data1);
}
Object data2 = c2.getLayoutData();
if (data2 == null || !(data2 instanceof SashFormData)) {
data2 = new SashFormData();
c2.setLayoutData(data2);
}
((SashFormData)data1).weight = (((long)b1.height << 16) + area.height - 1) / area.height;
((SashFormData)data2).weight = (((long)b2.height << 16) + area.height - 1) / area.height;
}
if (correction || (event.doit && event.detail != SWT.DRAG)) {
c1.setBounds(b1);
sash.setBounds(event.x, event.y, event.width, event.height);
c2.setBounds(b2);
}
}
@Override
public void setOrientation(int orientation) {
checkWidget();
if (orientation == SWT.RIGHT_TO_LEFT || orientation == SWT.LEFT_TO_RIGHT) {
super.setOrientation(orientation);
return;
}
if (getOrientation() == orientation) return;
if (orientation != SWT.HORIZONTAL && orientation != SWT.VERTICAL) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
sashStyle &= ~(SWT.HORIZONTAL | SWT.VERTICAL);
sashStyle |= orientation == SWT.VERTICAL ? SWT.HORIZONTAL : SWT.VERTICAL;
for (int i = 0; i < sashes.length; i++) {
sashes[i].dispose();
sashes[i] = createSash();
}
layout(false);
}
@Override
public void setBackground (Color color) {
super.setBackground(color);
background = color;
for (int i = 0; i < sashes.length; i++) {
sashes[i].setBackground(background);
}
}
@Override
public void setForeground (Color color) {
super.setForeground(color);
foreground = color;
for (int i = 0; i < sashes.length; i++) {
sashes[i].setForeground(foreground);
}
}
@Override
public void setLayout (Layout layout) {
checkWidget();
return;
}
public void setMaximizedControl(Control control){
checkWidget();
if (control == null) {
if (maxControl != null) {
this.maxControl = null;
layout(false);
for (int i= 0; i < sashes.length; i++){
sashes[i].setVisible(true);
}
}
return;
}
for (int i= 0; i < sashes.length; i++){
sashes[i].setVisible(false);
}
maxControl = control;
layout(false);
}
public void setSashWidth(int width) {
checkWidget();
if (SASH_WIDTH == width) return;
SASH_WIDTH = width;
layout(false);
}
@Override
public void setToolTipText(String string) {
super.setToolTipText(string);
for (int i = 0; i < sashes.length; i++) {
sashes[i].setToolTipText(string);
}
}
public void setWeights(int[] weights) {
checkWidget();
Control[] cArray = getControls(false);
if (weights == null || weights.length != cArray.length) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
int total = 0;
for (int i = 0; i < weights.length; i++) {
if (weights[i] < 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
total += weights[i];
}
if (total == 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data == null || !(data instanceof SashFormData)) {
data = new SashFormData();
cArray[i].setLayoutData(data);
}
((SashFormData)data).weight = (((long)weights[i] << 16) + total - 1) / total;
}
layout(false);
}
public void setLengths(int[] lengths) {
checkWidget();
Control[] cArray = getControls(false);
if (lengths == null || lengths.length != cArray.length) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
int total = 0;
for (int i = 0; i < lengths.length; i++) {
if (lengths[i] < 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
total += lengths[i];
}
if (total == 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data == null || !(data instanceof SashFormData)) {
data = new SashFormData();
cArray[i].setLayoutData(data);
}
((SashFormData)data).length = lengths[i];
}
layout(false);
}
}
SashFormData.java:
class SashFormData {
long weight;
int length;
String getName () {
String string = getClass ().getName ();
int index = string.lastIndexOf ('.');
if (index == -1) return string;
return string.substring (index + 1, string.length ());
}
@Override
public String toString () {
return getName()+" {length="+length+", weight="+weight+"}"; //$NON-NLS-2$
}
}
SashFormLayout.java:
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
class SashFormLayout extends Layout {
@Override
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
SashForm sashForm = (SashForm)composite;
Control[] cArray = sashForm.getControls(true);
int width = 0;
int height = 0;
if (cArray.length == 0) {
if (wHint != SWT.DEFAULT) width = wHint;
if (hHint != SWT.DEFAULT) height = hHint;
return new Point(width, height);
}
// determine control sizes
boolean vertical = sashForm.getOrientation() == SWT.VERTICAL;
if (sashForm.getWeighted()) {
int maxIndex = 0;
int maxValue = 0;
for (int i = 0; i < cArray.length; i++) {
if (vertical) {
Point size = cArray[i].computeSize(wHint, SWT.DEFAULT, flushCache);
if (size.y > maxValue) {
maxIndex = i;
maxValue = size.y;
}
width = Math.max(width, size.x);
} else {
Point size = cArray[i].computeSize(SWT.DEFAULT, hHint, flushCache);
if (size.x > maxValue) {
maxIndex = i;
maxValue = size.x;
}
height = Math.max(height, size.y);
}
}
// get the ratios
long[] ratios = new long[cArray.length];
long total = 0;
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
ratios[i] = ((SashFormData)data).weight;
} else {
data = new SashFormData();
cArray[i].setLayoutData(data);
((SashFormData)data).weight = ratios[i] = ((200 << 16) + 999) / 1000;
}
total += ratios[i];
}
if (ratios[maxIndex] > 0) {
int sashwidth = sashForm.sashes.length > 0 ? sashForm.SASH_WIDTH + sashForm.sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH;
if (vertical) {
height += (int)(total * maxValue / ratios[maxIndex]) + (cArray.length - 1) * sashwidth;
} else {
width += (int)(total * maxValue / ratios[maxIndex]) + (cArray.length - 1) * sashwidth;
}
}
} else {
int maxIndex = 0;
int maxValue = 0;
for (int i = 0; i < cArray.length; i++) {
if (vertical) {
Point size = cArray[i].computeSize(wHint, SWT.DEFAULT, flushCache);
if (size.y > maxValue) {
maxIndex = i;
maxValue = size.y;
}
width = Math.max(width, size.x);
} else {
Point size = cArray[i].computeSize(SWT.DEFAULT, hHint, flushCache);
if (size.x > maxValue) {
maxIndex = i;
maxValue = size.x;
}
height = Math.max(height, size.y);
}
}
// get the lengths
int[] lengths = new int[cArray.length];
long total = 0;
for (int i = 0; i < cArray.length; i++) {
Object data = cArray[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
lengths[i] = ((SashFormData)data).length;
} else {
data = new SashFormData();
cArray[i].setLayoutData(data);
((SashFormData)data).length = sashForm.getOrientation() == SWT.HORIZONTAL ? cArray[i].getSize().x : cArray[i].getSize().y;
}
total += lengths[i];
}
if (lengths[maxIndex] > 0) {
int sashwidth = sashForm.sashes.length > 0 ? sashForm.SASH_WIDTH + sashForm.sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH;
if (vertical) {
height += total + (cArray.length - 1) * sashwidth;
} else {
width += total + (cArray.length - 1) * sashwidth;
}
}
}
width += sashForm.getBorderWidth()*2;
height += sashForm.getBorderWidth()*2;
if (wHint != SWT.DEFAULT) width = wHint;
if (hHint != SWT.DEFAULT) height = hHint;
return new Point(width, height);
}
@Override
protected boolean flushCache(Control control) {
return true;
}
@Override
protected void layout(Composite composite, boolean flushCache) {
SashForm sashForm = (SashForm)composite;
Rectangle area = sashForm.getClientArea();
if (area.width <= 1 || area.height <= 1) return;
Control[] newControls = sashForm.getControls(true);
if (sashForm.controls.length == 0 && newControls.length == 0) return;
sashForm.controls = newControls;
Control[] controls = sashForm.controls;
if (sashForm.maxControl != null && !sashForm.maxControl.isDisposed()) {
for (int i= 0; i < controls.length; i++){
if (controls[i] != sashForm.maxControl) {
controls[i].setBounds(-200, -200, 0, 0);
} else {
controls[i].setBounds(area);
}
}
return;
}
// keep just the right number of sashes
if (sashForm.sashes.length < controls.length - 1) {
Sash[] newSashes = new Sash[controls.length - 1];
System.arraycopy(sashForm.sashes, 0, newSashes, 0, sashForm.sashes.length);
for (int i = sashForm.sashes.length; i < newSashes.length; i++) {
newSashes[i] = sashForm.createSash();
}
sashForm.sashes = newSashes;
}
if (sashForm.sashes.length > controls.length - 1) {
if (controls.length == 0) {
for (int i = 0; i < sashForm.sashes.length; i++) {
sashForm.sashes[i].dispose();
}
sashForm.sashes = new Sash[0];
} else {
Sash[] newSashes = new Sash[controls.length - 1];
System.arraycopy(sashForm.sashes, 0, newSashes, 0, newSashes.length);
for (int i = controls.length - 1; i < sashForm.sashes.length; i++) {
sashForm.sashes[i].dispose();
}
sashForm.sashes = newSashes;
}
}
if (controls.length == 0) return;
Sash[] sashes = sashForm.sashes;
if (sashForm.getWeighted()) {
// get the ratios
long[] ratios = new long[controls.length];
long total = 0;
for (int i = 0; i < controls.length; i++) {
Object data = controls[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
ratios[i] = ((SashFormData)data).weight;
} else {
data = new SashFormData();
controls[i].setLayoutData(data);
((SashFormData)data).weight = ratios[i] = ((200 << 16) + 999) / 1000;
}
total += ratios[i];
}
int sashwidth = sashes.length > 0 ? sashForm.SASH_WIDTH + sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH;
if (sashForm.getOrientation() == SWT.HORIZONTAL) {
int width = (int)(ratios[0] * (area.width - sashes.length * sashwidth) / total);
int x = area.x;
controls[0].setBounds(x, area.y, width, area.height);
x += width;
for (int i = 1; i < controls.length - 1; i++) {
sashes[i - 1].setBounds(x, area.y, sashwidth, area.height);
x += sashwidth;
width = (int)(ratios[i] * (area.width - sashes.length * sashwidth) / total);
controls[i].setBounds(x, area.y, width, area.height);
x += width;
}
if (controls.length > 1) {
sashes[sashes.length - 1].setBounds(x, area.y, sashwidth, area.height);
x += sashwidth;
width = area.width - x;
controls[controls.length - 1].setBounds(x, area.y, width, area.height);
}
} else {
int height = (int)(ratios[0] * (area.height - sashes.length * sashwidth) / total);
int y = area.y;
controls[0].setBounds(area.x, y, area.width, height);
y += height;
for (int i = 1; i < controls.length - 1; i++) {
sashes[i - 1].setBounds(area.x, y, area.width, sashwidth);
y += sashwidth;
height = (int)(ratios[i] * (area.height - sashes.length * sashwidth) / total);
controls[i].setBounds(area.x, y, area.width, height);
y += height;
}
if (controls.length > 1) {
sashes[sashes.length - 1].setBounds(area.x, y, area.width, sashwidth);
y += sashwidth;
height = area.height - y;
controls[controls.length - 1].setBounds(area.x, y, area.width, height);
}
}
} else {
// get the lengths
int[] lengths = new int[controls.length];
for (int i = 0; i < controls.length; i++) {
Object data = controls[i].getLayoutData();
if (data != null && data instanceof SashFormData) {
lengths[i] = ((SashFormData)data).length;
} else {
data = new SashFormData();
controls[i].setLayoutData(data);
((SashFormData)data).length = sashForm.getOrientation() == SWT.HORIZONTAL ? controls[i].getSize().x : controls[i].getSize().y;
}
}
int sashwidth = sashes.length > 0 ? sashForm.SASH_WIDTH + sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH;
if (sashForm.getOrientation() == SWT.HORIZONTAL) {
int width = lengths[0];
int x = area.x;
controls[0].setBounds(x, area.y, width, area.height);
x += width;
for (int i = 1; i < controls.length - 1; i++) {
sashes[i - 1].setBounds(x, area.y, sashwidth, area.height);
x += sashwidth;
width = lengths[i];
controls[i].setBounds(x, area.y, width, area.height);
x += width;
}
if (controls.length > 1) {
sashes[sashes.length - 1].setBounds(x, area.y, sashwidth, area.height);
x += sashwidth;
width = area.width - x;
controls[controls.length - 1].setBounds(x, area.y, width, area.height);
}
} else {
int height = lengths[0];
int y = area.y;
controls[0].setBounds(area.x, y, area.width, height);
y += height;
for (int i = 1; i < controls.length - 1; i++) {
sashes[i - 1].setBounds(area.x, y, area.width, sashwidth);
y += sashwidth;
height = lengths[i];
controls[i].setBounds(area.x, y, area.width, height);
y += height;
}
if (controls.length > 1) {
sashes[sashes.length - 1].setBounds(area.x, y, area.width, sashwidth);
y += sashwidth;
height = area.height - y;
controls[controls.length - 1].setBounds(area.x, y, area.width, height);
}
}
}
}
}