package org.eclipse.jface.layout; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.Control; /** * The FormDataBuilder creates and initializes FormData for a particular control. Instances are * created using one of the static method in this class. * * @since 3.4 */ public final class FormDataBuilder { private final FormData data; private final Control control; private boolean centerVertically = false; private int vertical; private boolean centerHorizontally = false; private int horizontal; private FormDataBuilder(Control control) { this.control = control; this.data = new FormData(); control.setLayoutData(data); } /** * Creates a new FormDataBuilder to attach the given control to points within the layout. * * @param control the control * * @return this */ public static FormDataBuilder position(Control control) { if (control == null) { throw new IllegalArgumentException("Control cannot be null"); } return new FormDataBuilder(control); } /** * Sets the minimum size of the control. If SWT.DEFAULT is used for the width or height, the * preferred size will be used for that parameter. * * @param width the minimum width * @param height the minimum height * @return this */ public FormDataBuilder size(int width, int height) { if ((width != SWT.DEFAULT && width < 0) || (height != SWT.DEFAULT && height < 0)) { throw new IllegalArgumentException(); } checkData(); data.width = width; data.height = height; applyCentering(); return this; } /** * Sets the minimum size of the control. If SWT.DEFAULT is used for the width or height, the * preferred size will be used for that parameter. * * @param size the minimum size * @return this */ public FormDataBuilder size(Point size) { return size(size.x, size.y); } /** * Sets the minimum width of the control. If SWT.DEFAULT is given, preferred size will be used. * * @param width the minimum width * @return this */ public FormDataBuilder width(int width) { if (width != SWT.DEFAULT && width < 0) { throw new IllegalArgumentException(); } checkData(); data.width = width; applyCentering(); return this; } /** * Sets the minimum height of the control. If SWT.DEFAULT is given, preferred size will be used. * * @param height the minimum height * @return this */ public FormDataBuilder height(int height) { if (height != SWT.DEFAULT && height < 0) { throw new IllegalArgumentException(); } checkData(); data.height = height; applyCentering(); return this; } /** * Horizontally centers the control given its current computed size. * * @return this */ public FormDataBuilder centerHorizontally() { return centerHorizontally(50); } /** * Horizontally centers the control to the position of the given percentage given its current * computed size. * * @param percentage the percentage * @return this */ public FormDataBuilder centerHorizontally(int percentage) { checkData(); centerHorizontally = true; horizontal = percentage; applyCentering(); return this; } /** * Vertically centers the control given its current computed size. * * @return this */ public FormDataBuilder centerVertically() { return centerVertically(50); } /** * Vertically centers the control to the position of the given percentage given its current * computed size. * * @param percentage the percentage * @return this */ public FormDataBuilder centerVertically(int percentage) { checkData(); centerVertically = true; vertical = percentage; applyCentering(); return this; } /** * Connects the left side of the control to the left side of the parent composite. * * @return this */ public FormDataBuilder left() { return left(0); } /** * Connects the left side of the control to the position of the given percentage. Thus a value * of 75 would attach the side to an invisible line 75% of the way across the parent composite. * * @param percentage the percentage * @return this */ public FormDataBuilder left(int percentage) { checkData(); clearHorizontalCentering(); data.left = new FormAttachment(percentage); return this; } /** * Attaches the left side of this control to the right side of the given control, with no * padding between them. * * @param control the control to which to attach * @return this */ public FormDataBuilder left(Control control) { return left(control, 0, SWT.RIGHT); } /** * Attaches the left side of this control to the right side of the given control, with the given * amount of padding between them. * * @param control the control to which to attach * @param padding the padding between the controls * @return this */ public FormDataBuilder left(Control control, int padding) { return left(control, padding, SWT.RIGHT); } /** * Attaches the left side of this control to the side of the given control, with the given * amount of padding between them. The side of the given control that we are attaching to is * given by the alignment, which will be one of SWT.LEFT, SWT.CENTER, or SWT.RIGHT. * * @param control the control to which to attach * @param padding the padding between the controls * @param alignment the side of the control to which to attach * @return this * * @throws IllegalArgumentException if the alignment is not one of the specified values. */ public FormDataBuilder left(Control control, int padding, int alignment) { if (alignment != SWT.LEFT && alignment != SWT.RIGHT && alignment != SWT.CENTER) { throw new IllegalArgumentException(); } checkData(); clearHorizontalCentering(); data.left = new FormAttachment(control, padding, alignment); return this; } /** * Connects the right side of the control to the right side of the parent composite. * * @return this */ public FormDataBuilder right() { return right(100); } /** * Connects the right side of the control to the position of the given percentage. Thus a value * of 75 would attach the side to an invisible line 75% of the way across the parent composite. * * @param percentage the percentage * @return this */ public FormDataBuilder right(int percentage) { checkData(); clearHorizontalCentering(); data.right = new FormAttachment(percentage); return this; } /** * Attaches the right side of this control to the left side of the given control, with no * padding between them. * * @param control the control to which to attach * @return this */ public FormDataBuilder right(Control control) { return right(control, 0, SWT.LEFT); } /** * Attaches the right side of this control to the left side of the given control, with the given * amount of padding between them. * * @param control the control to which to attach * @param padding the padding between the controls * @return this */ public FormDataBuilder right(Control control, int padding) { return right(control, padding, SWT.LEFT); } /** * Attaches the right side of this control to the side of the given control, with the given * amount of padding between them. The side of the given control that we are attaching to is * given by the alignment, which will be one of SWT.RIGHT, SWT.CENTER, or SWT.LEFT. * * @param control the control to which to attach * @param padding the padding between the controls * @param alignment the side of the control to which to attach * @return this * * @throws IllegalArgumentException if the alignment is not one of the specified values. */ public FormDataBuilder right(Control control, int padding, int alignment) { if (alignment != SWT.RIGHT && alignment != SWT.LEFT && alignment != SWT.CENTER) { throw new IllegalArgumentException(); } checkData(); clearHorizontalCentering(); data.right = new FormAttachment(control, -1 * padding, alignment); return this; } /** * Connects the top side of the control to the top of the parent composite. * * @return this */ public FormDataBuilder top() { return top(0); } /** * Connects the top side of the control to the position of the given percentage. Thus a value of * 75 would attach the side to an invisible line 75% of the way across the parent composite. * * @param percentage the percentage * @return this */ public FormDataBuilder top(int percentage) { checkData(); clearVerticalCentering(); data.top = new FormAttachment(percentage); return this; } /** * Attaches the top side of this control to the bottom side of the given control, with no * padding between them. * * @param control the control to which to attach * @return this */ public FormDataBuilder top(Control control) { return top(control, 0, SWT.BOTTOM); } /** * Attaches the top side of this control to the bottom side of the given control, with the given * amount of padding between them. * * @param control the control to which to attach * @param padding the padding between the controls * @return this */ public FormDataBuilder top(Control control, int padding) { return top(control, padding, SWT.BOTTOM); } /** * Attaches the top side of this control to the side of the given control, with the given amount * of padding between them. The side of the given control that we are attaching to is given by * the alignment, which will be one of SWT.TOP, SWT.CENTER, or SWT.BOTTOM. * * @param control the control to which to attach * @param padding the padding between the controls * @param alignment the side of the control to which to attach * @return this * * @throws IllegalArgumentException if the alignment is not one of the specified values. */ public FormDataBuilder top(Control control, int padding, int alignment) { if (alignment != SWT.TOP && alignment != SWT.BOTTOM && alignment != SWT.CENTER) { throw new IllegalArgumentException(); } checkData(); clearVerticalCentering(); data.top = new FormAttachment(control, padding, alignment); return this; } /** * Connects the bottom side of the control to the bottom of the parent composite. * * @return this */ public FormDataBuilder bottom() { return bottom(100); } /** * Connects the bottom side of the control to the position of the given percentage. Thus a value * of 75 would attach the side to an invisible line 75% of the way across the parent composite. * * @param percentage the percentage * @return this */ public FormDataBuilder bottom(int percentage) { checkData(); clearVerticalCentering(); data.bottom = new FormAttachment(percentage); return this; } /** * Attaches the bottom side of this control to the top side of the given control, with no * padding between them. * * @param control the control to which to attach * @return this */ public FormDataBuilder bottom(Control control) { return bottom(control, 0, SWT.TOP); } /** * Attaches the bottom side of this control to the top side of the given control, with the given * amount of padding between them. * * @param control the control to which to attach * @param padding the padding between the controls * @return this */ public FormDataBuilder bottom(Control control, int padding) { return bottom(control, padding, SWT.TOP); } /** * Attaches the bottom side of this control to the side of the given control, with the given * amount of padding between them. The side of the given control that we are attaching to is * given by the alignment, which will be one of SWT.TOP, SWT.CENTER, or SWT.BOTTOM. * * @param control the control to which to attach * @param padding the padding between the controls * @param alignment the side of the control to which to attach * @return this * * @throws IllegalArgumentException if the alignment is not one of the specified values. */ public FormDataBuilder bottom(Control control, int padding, int alignment) { if (alignment != SWT.TOP && alignment != SWT.BOTTOM && alignment != SWT.CENTER) { throw new IllegalArgumentException(); } checkData(); clearVerticalCentering(); data.bottom = new FormAttachment(control, -1 * padding, alignment); return this; } private final void applyCentering() { Point size = control.computeSize(data.width, data.height); if (centerHorizontally) { data.left = new FormAttachment(horizontal, -size.x / 2); data.right = new FormAttachment(horizontal, size.x / 2); } if (centerVertically) { data.top = new FormAttachment(vertical, -size.y / 2); data.bottom = new FormAttachment(vertical, size.y / 2); } control.setLayoutData(data); } private final void clearVerticalCentering() { if (centerVertically) { centerVertically = false; data.top = null; data.bottom = null; } } private final void clearHorizontalCentering() { if (centerHorizontally) { centerHorizontally = false; data.left = null; data.right = null; } } private final void checkData() { if (control.getLayoutData() != data) { throw new IllegalStateException( "The data associated to the control is not the data created by the builder."); } } }