Initial commit from SVN.

This commit is contained in:
wcrisman
2014-05-30 10:31:51 -07:00
commit b45e56b890
1968 changed files with 370949 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2007 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
public class CardLayout extends Layout {
/** The cached width. */
private int x = 0;
/** The cached height. */
private int y = 0;
/** The index of the control that will be displayed on top. */
public int topIndex = 0;
/** The top and bottom margins. */
public int marginHeight = 0;
/** The left and right margins. */
public int marginWidth = 0;
/**
* CardLayout constructor.
*/
public CardLayout() {
}//CardLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeCurrentSize(org.eclipse.swt.widgets.Composite)
*/
public Point computeCurrentSize(Composite composite) {
Point result = super.computeCurrentSize(composite);
result.x += marginWidth;
result.y += marginHeight;
return result;
}//computeCurrentSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int hintX, int hintY, boolean flushCache) {
Control[] children = composite.getChildren();
if(flushCache || x == 0 || y == 0) {
x = 0;
y = 0;
for(int index = 0; index < children.length; index++) {
Point childSize = children[index].computeSize(hintX, hintY);
x = Math.max(x, childSize.x);
y = Math.max(y, childSize.y);
}//for//
}//if//
return new Point(Math.max(x + (marginWidth << 1), hintX), Math.max(y + (marginHeight << 1), hintY));
}//computeSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#flushCache(org.eclipse.swt.widgets.Control)
*/
protected boolean flushCache(Control control) {
x = 0;
y = 0;
return true;
}//flushCache()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Control[] children = composite.getChildren();
if(children != null && children.length > 0) {
Rectangle bounds = composite.getClientArea();
int top = topIndex < 0 ? 0 : topIndex >= children.length ? children.length - 1 : topIndex;
bounds.x += marginWidth;
bounds.width -= marginWidth << 1;
bounds.y += marginHeight;
bounds.height -= marginHeight << 1;
for(int index = 0; index < children.length; index++) {
children[index].setBounds(bounds);
children[index].setVisible(index == top);
}//for//
}//if//
}//layout()//
}//CardLayout//

View File

@@ -0,0 +1,83 @@
package com.foundation.view.swt.layout;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* A very simple layout that centers the first child within the parent.
* All other children are not visible.
* There is no data attached to the children that is used by this layout.
*/
public class CenterLayout extends Layout {
private Point size = new Point(0, 0);
private Point firstChildSize = new Point(0, 0);
/**
* CenterLayout constructor.
*/
public CenterLayout() {
}//CenterLayout()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
if(flushCache) {
Control[] children = composite.getChildren();
size.x = 0;
size.y = 0;
firstChildSize.x = 0;
firstChildSize.y = 0;
if(children != null) {
for(int index = 0; index < children.length; index++) {
Point childSize = children[index].computeSize(wHint, hHint, flushCache);
size.x = Math.max(childSize.x, size.x);
size.y = Math.max(childSize.y, size.y);
if(index == 0) {
firstChildSize.x = childSize.x;
firstChildSize.y = childSize.y;
}//if//
}//for//
}//if//
}//if//
return new Point(size.x, size.y);
}//computeSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Rectangle space = composite.getClientArea();
Control[] children = composite.getChildren();
if(flushCache || firstChildSize.x == 0 || firstChildSize.y == 0) {
if(children != null && children.length > 0) {
Point childSize = children[0].computeSize(-1, -1, true);
firstChildSize.x = childSize.x;
firstChildSize.y = childSize.y;
}//if//
else {
firstChildSize.x = 0;
firstChildSize.y = 0;
}//else//
}//if//
if(children != null) {
for(int index = 0; index < children.length; index++) {
if(index == 0) {
children[index].setSize(firstChildSize);
children[index].setLocation(space.x + ((space.width - firstChildSize.x) >> 1), space.y + ((space.height - firstChildSize.y) >> 1));
}//if//
else {
children[index].setSize(0, 0);
children[index].setLocation(0, 0);
}//else//
}//for//
}//if//
}//layout()//
}//CenterLayout//

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2007,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* The data assigned to a component whose parent uses a FillLayout.
*/
public class FillData extends LayoutData {
/** The last generated default result (where the hints are the default: SWT.DEFAULT). */
private Point defaultResult = null;
/** The hints last used to create the lastHintResult. */
private int lastWidthHint = -1;
/** The hints last used to create the lastHintResult. */
private int lastHeightHint = -1;
/** The last generated result (where non-default hints are given). */
private Point lastHintResult = null;
/** The default width supplied by the view for the control this data describes. This overrides the control's desired width if it is not assigned SWT.DEFAULT. */
public int defaultWidth = SWT.DEFAULT;
/** The default height supplied by the view for the control this data describes. This overrides the control's desired height if it is not assigned SWT.DEFAULT. */
public int defaultHeight = SWT.DEFAULT;
/** The minimum width for the control. */
public int minWidth = -1;
/** The minimum height for the control. */
public int minHeight = -1;
/** The minimum width for the control. */
public int cachedMinWidth = -1;
/** The minimum height for the control. */
public int cachedMinHeight = -1;
/**
* FillData constructor.
*/
public FillData() {
super();
}//FillData()//
/**
* Computes the size of the control that this data describes.
* @param result The point that will contain the resulting size.
* @param control The control the data is describing.
* @param wHint The hint for the width, or SWT.DEFAULT if no hint is given.
* @param hHint The hint for the height, or SWT.DEFAULT if no hint is given.
* @param flushCache Whether to first flush the cache, forcing the control's size preferences to be re-assertained.
* @return The point describing the control's desired size.
*/
void computeSize(Point result, Control control, int wHint, int hHint, boolean flushCache) {
if(flushCache) {
flushCache();
}//if//
if(wHint == SWT.DEFAULT && hHint == SWT.DEFAULT) {
if(defaultResult == null) {
defaultResult = control.computeSize(defaultWidth, defaultHeight, flushCache);
}//if//
result.x = defaultResult.x;
result.y = defaultResult.y;
}//if//
else {
if(lastHintResult == null || wHint != lastWidthHint || hHint != lastHeightHint) {
lastHintResult = control.computeSize(wHint, hHint, flushCache);
lastWidthHint = wHint;
lastHeightHint = hHint;
}//if//
result.x = lastHintResult.x;
result.y = lastHintResult.y;
}//else//
}//computeSize()//
/**
* Releases all cached data.
*/
public void flushCache() {
defaultResult = null;
lastHintResult = null;
cachedMinWidth = -1;
cachedMinHeight = -1;
}//flushCache()//
}//FillData//

View File

@@ -0,0 +1,359 @@
/*
* Copyright (c) 2000, 2006 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
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Scrollable;
import com.foundation.view.swt.IOverlay;
/**
* <code>FillLayout</code> is the simplest layout class. It lays out
* controls in a single row or column, forcing them to be the same size.
* <p>
* Initially, the controls will all be as tall as the tallest control,
* and as wide as the widest. <code>FillLayout</code> does not wrap,
* but you can specify margins and spacing. You might use it to
* lay out buttons in a task bar or tool bar, or to stack checkboxes
* in a <code>Group</code>. <code>FillLayout</code> can also be used
* when a <code>Composite</code> only has one child. For example,
* if a <code>Shell</code> has a single <code>Group</code> child,
* <code>FillLayout</code> will cause the <code>Group</code> to
* completely fill the <code>Shell</code> (if margins are 0).
* </p>
* <p>
* Example code: first a <code>FillLayout</code> is created and
* its type field is set, and then the layout is set into the
* <code>Composite</code>. Note that in a <code>FillLayout</code>,
* children are always the same size, and they fill all available space.
* <pre>
* FillLayout fillLayout = new FillLayout();
* fillLayout.type = SWT.VERTICAL;
* shell.setLayout(fillLayout);
* </pre>
* </p>
*/
public final class FillLayout extends Layout {
/** Specifies how controls will be positioned within the layout. */
public int type = SWT.HORIZONTAL;
/** Specifies the number of pixels of horizontal margin that will be placed along the left and right edges of the layout. */
public int marginWidth = 0;
/** Specifies the number of pixels of vertical margin that will be placed along the top and bottom edges of the layout. */
public int marginHeight = 0;
/** Specifies the number of pixels between the edge of one cell and the edge of its neighbouring cell. */
public int spacing = 0;
/**
* FillLayout constructor.
*/
public FillLayout() {
}//FillLayout()//
/**
* FillLayout constructor.
* @param type The fill direction (HORIZONTAL | VERTICAL).
*/
public FillLayout(int type) {
this.type = type;
}//FillLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeCurrentSize(org.eclipse.swt.widgets.Composite)
*/
public Point computeCurrentSize(Composite composite) {
Point result = super.computeCurrentSize(composite);
result.x += marginWidth;
result.y += marginHeight;
return result;
}//computeCurrentSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
Control[] children = composite.getChildren();
int count = children.length;
int maxWidth = 0;
int maxHeight = 0;
int width = 0;
int height = 0;
Point size = new Point(0, 0);
for(int i = 0; i < children.length; i++) {
Control child = children[i];
int w = wHint;
int h = hHint;
if((child instanceof IOverlay) || (!child.getVisible())) {
count--;
}//if//
else {
if(count > 0) {
if(type == SWT.HORIZONTAL && wHint != SWT.DEFAULT) {
w = Math.max(0, (wHint - (count - 1) * spacing) / count);
}//if//
if(type == SWT.VERTICAL && hHint != SWT.DEFAULT) {
h = Math.max(0, (hHint - (count - 1) * spacing) / count);
}//if//
}//if//
computeChildSize(size, child, w, h, flushCache);
maxWidth = Math.max(maxWidth, size.x);
maxHeight = Math.max(maxHeight, size.y);
}//else//
}//for//
if(type == SWT.HORIZONTAL) {
width = count * maxWidth;
if(count != 0) {
width += (count - 1) * spacing;
}//if//
height = maxHeight;
}//if//
else {
width = maxWidth;
height = count * maxHeight;
if(count != 0) {
height += (count - 1) * spacing;
}//if//
}//else//
width += marginWidth * 2;
height += marginHeight * 2;
if(wHint != SWT.DEFAULT) {
width = wHint;
}//if//
if(hHint != SWT.DEFAULT) {
height = hHint;
}//if//
size.x = width;
size.y = height;
return size;
}//computeSize()//
/**
* Computes the size of the child control.
* @param control The child control.
* @param wHint The width hint, or -1.
* @param hHint The height hint, or -1.
* @param flushCache Whether to flush the child's cache.
* @return The child's size.
*/
private void computeChildSize(Point result, Control control, int wHint, int hHint, boolean flushCache) {
FillData data = (FillData) control.getLayoutData();
if(data == null) {
data = new FillData();
control.setLayoutData(data);
}//if//
if(wHint == SWT.DEFAULT && hHint == SWT.DEFAULT) {
data.computeSize(result, control, wHint, hHint, flushCache);
}//if//
else {
int trimX, trimY;
int w;
int h;
if(control instanceof Scrollable) {
Rectangle rect = ((Scrollable) control).computeTrim(0, 0, 0, 0);
trimX = rect.width;
trimY = rect.height;
}//if//
else {
trimX = trimY = control.getBorderWidth() * 2;
}//else//
w = wHint == SWT.DEFAULT ? wHint : Math.max(0, wHint - trimX);
h = hHint == SWT.DEFAULT ? hHint : Math.max(0, hHint - trimY);
data.computeSize(result, control, w, h, flushCache);
}//else//
}//computeChildSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#flushCache(org.eclipse.swt.widgets.Control)
*/
public boolean flushCache(Control control) {
Object data = control.getLayoutData();
if(data != null) {
((FillData) data).flushCache();
}//if//
return true;
}//flushCache()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Rectangle rect = composite.getClientArea();
Control[] children = composite.getChildren();
int count = children.length;
IOverlay[] overlayChildren = new IOverlay[children.length];
int overlayCount = 0;
//Declarative Engineering//
//Ignore invisible and overlay children.//
for(int index = children.length - 1; index >= 0; index--) {
if((children[index] instanceof IOverlay) || (!children[index].getVisible())) {
if(children[index] instanceof IOverlay) {
overlayChildren[overlayCount++] = (IOverlay) children[index];
}//if//
if(index + 1 != count) {
System.arraycopy(children, index + 1, children, index, children.length - index - 1);
}//if//
count--;
}//if//
}//for//
if(count != 0) {
int width = rect.width - marginWidth * 2;
int height = rect.height - marginHeight * 2;
int x;
int y;
int extra;
if(type == SWT.HORIZONTAL) {
int cellWidth;
width -= (count - 1) * spacing;
x = rect.x + marginWidth;
y = rect.y + marginHeight;
extra = width % count;
cellWidth = width / count;
for(int i = 0; i < count; i++) {
Control child = children[i];
int childWidth = cellWidth;
if(i == 0) {
childWidth += extra / 2;
}//if//
else if(i == count - 1) {
childWidth += (extra + 1) / 2;
}//else if//
child.setBounds(x, y, childWidth, height);
x += childWidth + spacing;
}//for//
}//if//
else {
int cellHeight;
height -= (count - 1) * spacing;
x = rect.x + marginWidth;
y = rect.y + marginHeight;
cellHeight = height / count;
extra = height % count;
for(int i = 0; i < count; i++) {
Control child = children[i];
int childHeight = cellHeight;
if(i == 0) {
childHeight += extra / 2;
}//if//
else if(i == count - 1) {
childHeight += (extra + 1) / 2;
}//else if//
child.setBounds(x, y, width, childHeight);
y += childHeight + spacing;
}//for//
}//else//
if(overlayCount > 0) { //Layout the overlays.//
int upperLeftOffset = 0;
int upperRightOffset = 0;
int lowerLeftOffset = 0;
int lowerRightOffset = 0;
Control lastPeer = null;
Arrays.sort(overlayChildren, 0, overlayCount, new Comparator() {
public int compare(Object arg0, Object arg1) {
return ((IOverlay) arg0).getPeerControl().hashCode() - ((IOverlay) arg1).getPeerControl().hashCode();
}//compare()//
});
for(int index = 0; index < overlayCount; index++) {
IOverlay overlay = overlayChildren[index];
Control peer = overlay.getPeerControl();
Rectangle bounds = peer.getBounds();
Point size = overlay.getSize();
if(peer != lastPeer) {
upperLeftOffset = 0;
upperRightOffset = 0;
lowerLeftOffset = 0;
lowerRightOffset = 0;
lastPeer = peer;
}//if//
switch(overlay.getPosition()) {
case IOverlay.POSITION_UPPER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + upperLeftOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperLeftOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_UPPER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - upperRightOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - lowerRightOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + lowerLeftOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerLeftOffset += bounds.width + 1;
break;
}//case//
}//switch//
((Control) overlay).setBounds(bounds);
}//for//
}//if//
}//if//
}//layout()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return "FillLayout {type: " + (type == SWT.VERTICAL ? "VERTICAL; " : "HORIZONTAL; ") + "marginWidth: " + marginWidth + "; marginHeight: " + marginHeight + "; spacing: " + spacing + "}";
}//toString()//
}//FillLayout//

View File

@@ -0,0 +1,300 @@
/*
* Copyright (c) 2000, 2006 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 com.foundation.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
/**
* Instances of this class are used to define the edges of a control
* within a <code>FormLayout</code>.
* <p>
* <code>FormAttachments</code> are set into the top, bottom, left,
* and right fields of the <code>FormData</code> for a control.
* For example:
* <pre>
* FormData data = new FormData();
* data.top = new FormAttachment(0,5);
* data.bottom = new FormAttachment(100,-5);
* data.left = new FormAttachment(0,5);
* data.right = new FormAttachment(100,-5);
* button.setLayoutData(data);
* </pre>
* </p>
* <p>
* A <code>FormAttachment</code> defines where to attach the side of
* a control by using the equation, y = ax + b. The "a" term represents
* a fraction of the parent composite's width (from the left) or height
* (from the top). It can be defined using a numerator and denominator,
* or just a percentage value. If a percentage is used, the denominator
* is set to 100. The "b" term in the equation represents an offset, in
* pixels, from the attachment position. For example:
* <pre>
* FormAttachment attach = new FormAttachment (20, -5);
* </pre>
* specifies that the side to which the <code>FormAttachment</code>
* object belongs will lie at 20% of the parent composite, minus 5 pixels.
* </p>
* <p>
* Control sides can also be attached to another control.
* For example:
* <pre>
* FormAttachment attach = new FormAttachment (button, 10);
* </pre>
* specifies that the side to which the <code>FormAttachment</code>
* object belongs will lie in the same position as the adjacent side of
* the <code>button</code> control, plus 10 pixels. The control side can
* also be attached to the opposite side of the specified control.
* For example:
* <pre>
* FormData data = new FormData ();
* data.left = new FormAttachment (button, 0, SWT.LEFT);
* </pre>
* specifies that the left side of the control will lie in the same position
* as the left side of the <code>button</code> control. The control can also
* be attached in a position that will center the control on the specified
* control. For example:
* <pre>
* data.left = new FormAttachment (button, 0, SWT.CENTER);
* </pre>
* specifies that the left side of the control will be positioned so that it is
* centered between the left and right sides of the <code>button</code> control.
* If the alignment is not specified, the default is to attach to the adjacent side.
* </p>
*
* @see FormLayout
* @see FormData
*
* @since 2.0
*/
public final class FormAttachment {
/**
* numerator specifies the numerator of the "a" term in the
* equation, y = ax + b, which defines the attachment.
*/
public int numerator;
/**
* denominator specifies the denominator of the "a" term in the
* equation, y = ax + b, which defines the attachment.
*
* The default value is 100.
*/
public int denominator = 100;
/**
* offset specifies the offset, in pixels, of the control side
* from the attachment position.
* If the offset is positive, then the control side is offset
* to the right of or below the attachment position. If it is
* negative, then the control side is offset to the left of or
* above the attachment position.
*
* This is equivalent to the "b" term in the equation y = ax + b.
* The default value is 0.
*/
public int offset;
/**
* control specifies the control to which the control side is
* attached.
*/
public Control control;
/**
* alignment specifies the alignment of the control side that is
* attached to a control.
* <p>
* For top and bottom attachments, TOP, BOTTOM and CENTER are used. For left
* and right attachments, LEFT, RIGHT and CENTER are used. If any other case
* occurs, the default will be used instead.
* </p>
*
* <br>Possible values are: <ul>
* <li>TOP: Attach the side to the top side of the specified control.</li>
* <li>BOTTOM : Attach the side to the bottom side of the specified control.</li>
* <li>LEFT: Attach the side to the left side of the specified control.</li>
* <li>RIGHT: Attach the side to the right side of the specified control.</li>
* <li>CENTER: Attach the side at a position which will center the control on the specified control.</li>
* <li>DEFAULT: Attach the side to the adjacent side of the specified control.</li>
* </ul>
*/
public int alignment;
/**
* Constructs a new instance of this class.
* Since no numerator, denominator or offset is specified,
* the attachment is treated as a percentage of the form.
* The numerator is zero, the denominator is 100 and the
* offset is zero.
*
* @since 3.2
*/
public FormAttachment () {
}
/**
* Constructs a new instance of this class given a numerator
* Since no denominator or offset is specified, the default
* is to treat the numerator as a percentage of the form, with a
* denominator of 100. The offset is zero.
*
* @param numerator the percentage of the position
*
* @since 3.0
*/
public FormAttachment (int numerator) {
this (numerator, 100, 0);
}
/**
* Constructs a new instance of this class given a numerator
* and an offset. Since no denominator is specified, the default
* is to treat the numerator as a percentage of the form, with a
* denominator of 100.
*
* @param numerator the percentage of the position
* @param offset the offset of the side from the position
*/
public FormAttachment (int numerator, int offset) {
this (numerator, 100, offset);
}
/**
* Constructs a new instance of this class given a numerator
* and denominator and an offset. The position of the side is
* given by the fraction of the form defined by the numerator
* and denominator.
*
* @param numerator the numerator of the position
* @param denominator the denominator of the position
* @param offset the offset of the side from the position
*/
public FormAttachment (int numerator, int denominator, int offset) {
if (denominator == 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
this.numerator = numerator;
this.denominator = denominator;
this.offset = offset;
}
/**
* Constructs a new instance of this class given a control.
* Since no alignment is specified, the default alignment is
* to attach the side to the adjacent side of the specified
* control. Since no offset is specified, an offset of 0 is
* used.
*
* @param control the control the side is attached to
*/
public FormAttachment (Control control) {
this (control, 0, SWT.DEFAULT);
}
/**
* Constructs a new instance of this class given a control
* and an offset. Since no alignment is specified, the default
* alignment is to attach the side to the adjacent side of the
* specified control.
*
* @param control the control the side is attached to
* @param offset the offset of the side from the control
*/
public FormAttachment (Control control, int offset) {
this (control, offset, SWT.DEFAULT);
}
/**
* Constructs a new instance of this class given a control,
* an offset and an alignment.
*
* @param control the control the side is attached to
* @param offset the offset of the side from the control
* @param alignment the alignment of the side to the control it is attached to
*/
public FormAttachment (Control control, int offset, int alignment) {
this.control = control;
this.offset = offset;
this.alignment = alignment;
}
FormAttachment divide (int value) {
return new FormAttachment (numerator, denominator * value, offset / value);
}
int gcd (int m, int n) {
int temp;
m = Math.abs (m);
n = Math.abs (n);
if (m < n) {
temp = m;
m = n;
n = temp;
}
while (n != 0){
temp = m;
m = n;
n = temp % n;
}
return m;
}
FormAttachment minus (FormAttachment attachment) {
FormAttachment solution = new FormAttachment ();
solution.numerator = numerator * attachment.denominator - denominator * attachment.numerator;
solution.denominator = denominator * attachment.denominator;
int gcd = gcd (solution.denominator, solution.numerator);
solution.numerator = solution.numerator / gcd;
solution.denominator = solution.denominator / gcd;
solution.offset = offset - attachment.offset;
return solution;
}
FormAttachment minus (int value) {
return new FormAttachment (numerator, denominator, offset - value);
}
FormAttachment plus (FormAttachment attachment) {
FormAttachment solution = new FormAttachment ();
solution.numerator = numerator * attachment.denominator + denominator * attachment.numerator;
solution.denominator = denominator * attachment.denominator;
int gcd = gcd (solution.denominator, solution.numerator);
solution.numerator = solution.numerator / gcd;
solution.denominator = solution.denominator / gcd;
solution.offset = offset + attachment.offset;
return solution;
}
FormAttachment plus (int value) {
return new FormAttachment (numerator, denominator, offset + value);
}
int solveX (int value) {
if (denominator == 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
return ((numerator * value) / denominator) + offset;
}
int solveY (int value) {
if (numerator == 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
return (value - offset) * denominator / numerator;
}
/**
* Returns a string containing a concise, human-readable
* description of the receiver.
*
* @return a string representation of the FormAttachment
*/
public String toString () {
String string = control != null ? control.toString () : numerator + "/" + denominator;
return "{y = (" + string + (offset >= 0 ? ")x + " + offset: ")x - " + (-offset))+"}";
}
}

View File

@@ -0,0 +1,355 @@
/*
* Copyright (c) 2000, 2006 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
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* Instances of this class are used to define the attachments
* of a control in a <code>FormLayout</code>.
* <p>
* To set a <code>FormData</code> object into a control, you use the
* <code>setLayoutData ()</code> method. To define attachments for the
* <code>FormData</code>, set the fields directly, like this:
* <pre>
* FormData data = new FormData();
* data.left = new FormAttachment(0,5);
* data.right = new FormAttachment(100,-5);
* button.setLayoutData(formData);
* </pre>
* </p>
* <p>
* <code>FormData</code> contains the <code>FormAttachments</code> for
* each edge of the control that the <code>FormLayout</code> uses to
* determine the size and position of the control. <code>FormData</code>
* objects also allow you to set the width and height of controls within
* a <code>FormLayout</code>.
* </p>
* @see FormLayout
* @see FormAttachment
*/
public final class FormData {
/** Specifies the preferred width in pixels. This value is the wHint passed into Control.computeSize(int, int, boolean) to determine the preferred size of the control. */
public int width = SWT.DEFAULT;
/** Specifies the preferred height in pixels. This value is the hHint passed into Control.computeSize(int, int, boolean) to determine the preferred size of the control. */
public int height = SWT.DEFAULT;
/** Specifies the attachment of the left side of the control. */
public FormAttachment left;
/** Specifies the attachment of the right side of the control. */
public FormAttachment right;
/** Specifies the attachment of the top of the control. */
public FormAttachment top;
/** Specifies the attachment of the bottom of the control. */
public FormAttachment bottom;
int cacheWidth = -1;
int cacheHeight = -1;
int defaultWhint;
int defaultHhint;
int defaultWidth = -1;
int defaultHeight = -1;
int currentWhint;
int currentHhint;
int currentWidth = -1;
int currentHeight = -1;
FormAttachment cacheLeft;
FormAttachment cacheRight;
FormAttachment cacheTop;
FormAttachment cacheBottom;
boolean isVisited;
boolean needed;
/**
* Constructs a new instance of FormData using default values.
*/
public FormData() {
}//FormData()//
/**
* Constructs a new instance of FormData according to the parameters.
* A value of SWT.DEFAULT indicates that no minimum width or no minimum height is specified.
* @param width a minimum width for the control
* @param height a minimum height for the control
*/
public FormData(int width, int height) {
this.width = width;
this.height = height;
}//FormData()//
void computeSize(Control control, int wHint, int hHint, boolean flushCache) {
if(cacheWidth != -1 && cacheHeight != -1)
return;
if(wHint == this.width && hHint == this.height) {
if(defaultWidth == -1 || defaultHeight == -1 || wHint != defaultWhint || hHint != defaultHhint) {
Point size = control.computeSize(wHint, hHint, flushCache);
defaultWhint = wHint;
defaultHhint = hHint;
defaultWidth = size.x;
defaultHeight = size.y;
}
cacheWidth = defaultWidth;
cacheHeight = defaultHeight;
return;
}
if(currentWidth == -1 || currentHeight == -1 || wHint != currentWhint || hHint != currentHhint) {
Point size = control.computeSize(wHint, hHint, flushCache);
currentWhint = wHint;
currentHhint = hHint;
currentWidth = size.x;
currentHeight = size.y;
}
cacheWidth = currentWidth;
cacheHeight = currentHeight;
}//computeSize()//
void flushCache() {
cacheWidth = cacheHeight = -1;
defaultHeight = defaultWidth = -1;
currentHeight = currentWidth = -1;
}//flushCache()//
int getWidth(Control control, boolean flushCache) {
needed = true;
computeSize(control, width, height, flushCache);
return cacheWidth;
}//getWidth()//
int getHeight(Control control, boolean flushCache) {
computeSize(control, width, height, flushCache);
return cacheHeight;
}//getHeight()//
FormAttachment getBottomAttachment(Control control, int spacing, boolean flushCache) {
if(cacheBottom != null)
return cacheBottom;
if(isVisited)
return cacheBottom = new FormAttachment(0, getHeight(control, flushCache));
if(bottom == null) {
if(top == null)
return cacheBottom = new FormAttachment(0, getHeight(control, flushCache));
return cacheBottom = getTopAttachment(control, spacing, flushCache).plus(getHeight(control, flushCache));
}
Control bottomControl = bottom.control;
if(bottomControl != null) {
if(bottomControl.isDisposed()) {
bottom.control = bottomControl = null;
}
else {
if(bottomControl.getParent() != control.getParent()) {
bottomControl = null;
}
}
}
if(bottomControl == null)
return cacheBottom = bottom;
//Declarative Engineering: If the bottom control is not visible then use it's bottom attachment instead. This allows the invisible components to not waste space.//
if(!bottomControl.getVisible())
return ((FormData) bottomControl.getLayoutData()).getBottomAttachment(bottomControl, spacing, flushCache);
isVisited = true;
FormData bottomData = (FormData) bottomControl.getLayoutData();
FormAttachment bottomAttachment = bottomData.getBottomAttachment(bottomControl, spacing, flushCache);
switch(bottom.alignment) {
case SWT.BOTTOM:
cacheBottom = bottomAttachment.plus(bottom.offset);
break;
case SWT.CENTER: {
FormAttachment topAttachment = bottomData.getTopAttachment(bottomControl, spacing, flushCache);
FormAttachment bottomHeight = bottomAttachment.minus(topAttachment);
cacheBottom = bottomAttachment.minus(bottomHeight.minus(getHeight(control, flushCache)).divide(2));
break;
}
default: {
FormAttachment topAttachment = bottomData.getTopAttachment(bottomControl, spacing, flushCache);
cacheBottom = topAttachment.plus(bottom.offset - spacing);
break;
}
}
isVisited = false;
return cacheBottom;
}//getBottomAttachment()//
FormAttachment getLeftAttachment(Control control, int spacing, boolean flushCache) {
if(cacheLeft != null)
return cacheLeft;
if(isVisited)
return cacheLeft = new FormAttachment(0, 0);
if(left == null) {
if(right == null)
return cacheLeft = new FormAttachment(0, 0);
return cacheLeft = getRightAttachment(control, spacing, flushCache).minus(getWidth(control, flushCache));
}
Control leftControl = left.control;
if(leftControl != null) {
if(leftControl.isDisposed()) {
left.control = leftControl = null;
}
else {
if(leftControl.getParent() != control.getParent()) {
leftControl = null;
}
}
}
if(leftControl == null)
return cacheLeft = left;
isVisited = true;
FormData leftData = (FormData) leftControl.getLayoutData();
FormAttachment leftAttachment = leftData.getLeftAttachment(leftControl, spacing, flushCache);
switch(left.alignment) {
case SWT.LEFT:
cacheLeft = leftAttachment.plus(left.offset);
break;
case SWT.CENTER: {
FormAttachment rightAttachment = leftData.getRightAttachment(leftControl, spacing, flushCache);
FormAttachment leftWidth = rightAttachment.minus(leftAttachment);
cacheLeft = leftAttachment.plus(leftWidth.minus(getWidth(control, flushCache)).divide(2));
break;
}
default: {
FormAttachment rightAttachment = leftData.getRightAttachment(leftControl, spacing, flushCache);
cacheLeft = rightAttachment.plus(left.offset + spacing);
}
}
isVisited = false;
return cacheLeft;
}//getLeftAttachment()//
FormAttachment getRightAttachment(Control control, int spacing, boolean flushCache) {
if(cacheRight != null)
return cacheRight;
if(isVisited)
return cacheRight = new FormAttachment(0, getWidth(control, flushCache));
if(right == null) {
if(left == null)
return cacheRight = new FormAttachment(0, getWidth(control, flushCache));
return cacheRight = getLeftAttachment(control, spacing, flushCache).plus(getWidth(control, flushCache));
}
Control rightControl = right.control;
if(rightControl != null) {
if(rightControl.isDisposed()) {
right.control = rightControl = null;
}
else {
if(rightControl.getParent() != control.getParent()) {
rightControl = null;
}
}
}
if(rightControl == null)
return cacheRight = right;
isVisited = true;
FormData rightData = (FormData) rightControl.getLayoutData();
FormAttachment rightAttachment = rightData.getRightAttachment(rightControl, spacing, flushCache);
switch(right.alignment) {
case SWT.RIGHT:
cacheRight = rightAttachment.plus(right.offset);
break;
case SWT.CENTER: {
FormAttachment leftAttachment = rightData.getLeftAttachment(rightControl, spacing, flushCache);
FormAttachment rightWidth = rightAttachment.minus(leftAttachment);
cacheRight = rightAttachment.minus(rightWidth.minus(getWidth(control, flushCache)).divide(2));
break;
}
default: {
FormAttachment leftAttachment = rightData.getLeftAttachment(rightControl, spacing, flushCache);
cacheRight = leftAttachment.plus(right.offset - spacing);
break;
}
}
isVisited = false;
return cacheRight;
}//getRightAttachment()//
/**
* Gets the top attachment.
* @param control
* @param spacing
* @param flushCache
* @return
*/
FormAttachment getTopAttachment(Control control, int spacing, boolean flushCache) {
if(cacheTop == null) {
if(isVisited) {
cacheTop = new FormAttachment(0, 0);
}//if//
else if(top == null) {
if(bottom == null) {
cacheTop = new FormAttachment(0, 0);
}//if//
else {
cacheTop = getBottomAttachment(control, spacing, flushCache).minus(getHeight(control, flushCache));
}//else//
}//else if//
else {
Control topControl = top.control;
if(topControl != null) {
if(topControl.isDisposed()) {
top.control = topControl = null;
}//if//
else if(topControl.getParent() != control.getParent()) {
topControl = null;
}//else if//
}//if//
if(topControl == null) {
cacheTop = top;
}//if//
else {
isVisited = true;
FormData topData = (FormData) topControl.getLayoutData();
FormAttachment topAttachment = topData.getTopAttachment(topControl, spacing, flushCache);
switch(top.alignment) {
case SWT.TOP: {
cacheTop = topAttachment.plus(top.offset);
break;
}//case//
case SWT.CENTER: {
FormAttachment bottomAttachment = topData.getBottomAttachment(topControl, spacing, flushCache);
FormAttachment topHeight = bottomAttachment.minus(topAttachment);
cacheTop = topAttachment.plus(topHeight.minus(getHeight(control, flushCache)).divide(2));
break;
}//case//
default: {
FormAttachment bottomAttachment = topData.getBottomAttachment(topControl, spacing, flushCache);
cacheTop = bottomAttachment.plus(top.offset + spacing);
break;
}//default//
}//switch//
isVisited = false;
}//else//
}//else//
}//if//
return cacheTop;
}//getTopAttachment()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
String string = "FormData {";
if(width != SWT.DEFAULT)
string += "width=" + width + " ";
if(height != SWT.DEFAULT)
string += "height=" + height + " ";
if(left != null)
string += "left=" + left + " ";
if(right != null)
string += "right=" + right + " ";
if(top != null)
string += "top=" + top + " ";
if(bottom != null)
string += "bottom=" + bottom + " ";
string = string.trim();
string += "}";
return string;
}//toString()//
}//FormData//

View File

@@ -0,0 +1,543 @@
/*
* Copyright (c) 2000, 2006 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
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import com.foundation.view.swt.IOverlay;
/**
* <p>This is a modified version of the Eclipse layout.</p>
* Instances of this class control the position and size of the
* children of a composite control by using <code>FormAttachments</code>
* to optionally configure the left, top, right and bottom edges of
* each child.
* <p>
* The following example code creates a <code>FormLayout</code> and then sets
* it into a <code>Shell</code>:
* <pre>
* Display display = new Display ();
* Shell shell = new Shell(display);
* FormLayout layout = new FormLayout();
* layout.marginWidth = 3;
* layout.marginHeight = 3;
* shell.setLayout(layout);
* </pre>
* </p>
* <p>
* To use a <code>FormLayout</code>, create a <code>FormData</code> with
* <code>FormAttachment</code> for each child of <code>Composite</code>.
* The following example code attaches <code>button1</code> to the top
* and left edge of the composite and <code>button2</code> to the right
* edge of <code>button1</code> and the top and right edges of the
* composite:
* <pre>
* FormData data1 = new FormData();
* data1.left = new FormAttachment(0, 0);
* data1.top = new FormAttachment(0, 0);
* button1.setLayoutData(data1);
* FormData data2 = new FormData();
* data2.left = new FormAttachment(button1);
* data2.top = new FormAttachment(0, 0);
* data2.right = new FormAttachment(100, 0);
* button2.setLayoutData(data2);
* </pre>
* </p>
* <p>
* Each side of a child control can be attached to a position in the parent
* composite, or to other controls within the <code>Composite</code> by
* creating instances of <code>FormAttachment</code> and setting them into
* the top, bottom, left, and right fields of the child's <code>FormData</code>.
* </p>
* <p>
* If a side is not given an attachment, it is defined as not being attached
* to anything, causing the child to remain at its preferred size. If a child
* is given no attachment on either the left or the right or top or bottom, it is
* automatically attached to the left and top of the composite respectively.
* The following code positions <code>button1</code> and <code>button2</code>
* but relies on default attachments:
* <pre>
* FormData data2 = new FormData();
* data2.left = new FormAttachment(button1);
* data2.right = new FormAttachment(100, 0);
* button2.setLayoutData(data2);
* </pre>
* </p>
* <p>
* IMPORTANT: Do not define circular attachments. For example, do not attach
* the right edge of <code>button1</code> to the left edge of <code>button2</code>
* and then attach the left edge of <code>button2</code> to the right edge of
* <code>button1</code>. This will over constrain the layout, causing undefined
* behavior. The algorithm will terminate, but the results are undefined.
* </p>
*
* @see FormData
* @see FormAttachment
*
* @since 2.0
*
*/
public final class FormLayout extends Layout {
/** Specifies the number of pixels of horizontal margin that will be placed along the left and right edges of the layout. */
public int marginWidth = 0;
/** Specifies the number of pixels of vertical margin that will be placed along the top and bottom edges of the layout. */
public int marginHeight = 0;
/** Specifies the number of pixels of horizontal margin that will be placed along the left edge of the layout. */
public int marginLeft = 0;
/** Specifies the number of pixels of vertical margin that will be placed along the top edge of the layout. */
public int marginTop = 0;
/** Specifies the number of pixels of horizontal margin that will be placed along the right edge of the layout. */
public int marginRight = 0;
/** Specifies the number of pixels of vertical margin that will be placed along the bottom edge of the layout. */
public int marginBottom = 0;
/** Specifies the number of pixels between the edge of one control and the edge of its neighbouring control. */
public int spacing = 0;
/** The cached minimum width. Saves us having to layout to figure it out. */
private int cachedMinWidth = -1;
/** The cached minimum height. Saves us having to layout to figure it out. */
private int cachedMinHeight = -1;
/**
* Constructs a new instance of this class.
*/
public FormLayout() {
}//FormLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeCurrentSize(org.eclipse.swt.widgets.Composite)
*/
public Point computeCurrentSize(Composite composite) {
Point result = super.computeCurrentSize(composite);
result.x += marginRight + marginWidth;
result.y += marginBottom + marginHeight;
return result;
}//computeCurrentSize()//
/**
* Computes the preferred height of the form with respect to the preferred height of the control.
* <p>Given that the equations for top (T) and bottom (B) of the control in terms of the height of the form (X) are:<pre>
* T = AX + B
* B = CX + D</pre></p>
* <p>The equation for the height of the control (H) is bottom (B) minus top (T) or (H = B - T) or:</pre>
* H = (CX + D) - (AX + B)</pre></p>
*
* <p>Solving for (X), the height of the form, we get:</pre>
* X = (H + B - D) / (C - A)</pre></p>
*
* When (A = C), (C - A = 0) and the equation has no
* solution for X. This is a special case meaning that
* the control does not constrain the height of the
* form. In this case, we need to arbitrarily define
* the height of the form (X):<pre>
*
* Case 1: A = C, A = 0, C = 0
*
* Let X = D, the distance from the top of the form
* to the bottom edge of the control. In this case,
* the control was attatched to the top of the form
* and the form needs to be large enough to show the
* bottom edge of the control.
*
* Case 2: A = C, A = 1, C = 1
*
* Let X = -B, the distance from the bottom of the
* form to the top edge of the control. In this case,
* the control was attached to the bottom of the form
* and the only way that the control would be visible
* is if the offset is negative. If the offset is
* positive, there is no possible height for the form
* that will show the control as it will always be
* below the bottom edge of the form.
*
* Case 3: A = C, A != 0, C != 0 and A != 1, C != 0
*
* Let X = D / (1 - C), the distance from the top of the
* form to the bottom edge of the control. In this case,
* since C is not 0 or 1, it must be a fraction, U / V.
* The offset D is the distance from CX to the bottom edge
* of the control. This represents a fraction of the form
* (1 - C)X. Since the height of a fraction of the form is
* known, the height of the entire form can be found by setting
* (1 - C)X = D. We solve this equation for X in terms of U
* and V, giving us X = (U * D) / (U - V). Similarily, if the
* offset D is negative, the control is positioned above CX.
* The offset -B is the distance from the top edge of the control
* to CX. We can find the height of the entire form by setting
* CX = -B. Solving in terms of U and V gives us X = (-B * V) / U.
* </pre>
*/
int computeHeight(Control control, FormData data, boolean flushCache) {
FormAttachment top = data.getTopAttachment(control, spacing, flushCache);
FormAttachment bottom = data.getBottomAttachment(control, spacing, flushCache);
FormAttachment height = bottom.minus(top);
int result;
if(height.numerator == 0) {
if(bottom.numerator == 0) {
result = bottom.offset;
}//if//
else if(bottom.numerator == bottom.denominator) {
result = -top.offset;
}//else if//
else if(bottom.offset <= 0) {
result = -top.offset * top.denominator / bottom.numerator;
}//else if//
else {
result = bottom.denominator * bottom.offset / (bottom.denominator - bottom.numerator);
}//else//
}//if//
else {
result = height.solveY(data.getHeight(control, flushCache));
}//else//
return result;
}//computeHeight()//
/**
* Computes the preferred width of the form with respect to the preferred width of the control.
*/
int computeWidth(Control control, FormData data, boolean flushCache) {
FormAttachment left = data.getLeftAttachment(control, spacing, flushCache);
FormAttachment right = data.getRightAttachment(control, spacing, flushCache);
FormAttachment width = right.minus(left);
int result;
if(width.numerator == 0) {
if(right.numerator == 0) {
result = right.offset;
}//if//
else if(right.numerator == right.denominator) {
result = -left.offset;
}//else if//
else if(right.offset <= 0) {
result = -left.offset * left.denominator / left.numerator;
}//else if//
else {
result = right.denominator * right.offset / (right.denominator - right.numerator);
}//else//
}//if//
else {
result = width.solveY(data.getWidth(control, flushCache));
}//else//
return result;
}//computeWidth()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
Point size = layout(composite, false, 0, 0, wHint, hHint, flushCache);
if(wHint != SWT.DEFAULT) {
size.x = wHint;
}//if//
if(hHint != SWT.DEFAULT) {
size.y = hHint;
}//if//
return size;
}//computeSize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeMinSize(org.eclipse.swt.graphics.Point, org.eclipse.swt.widgets.Composite, boolean)
*/
public void computeMinSize(Point result, Composite composite, boolean flushCache) {
//TODO: Finish implementing - didn't finish because this layout is currently never used. The layout method will need modifications to get the minimum size and update the cached values.
// if(flushCache) {
// cachedMinWidth = -1;
// cachedMinHeight = -1;
// }//if//
//
// if(cachedMinWidth == -1 || cachedMinHeight == -1) {
// layout(composite, false, 0, 0, -1, -1, flushCache);
// }//if//
//
// result.x = cachedMinWidth;
// result.y = cachedMinHeight;
result.x = 0;
result.y = 0;
}//computeMinSize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#flushCache(org.eclipse.swt.widgets.Control)
*/
public boolean flushCache(Control control) {
Object data = control.getLayoutData();
if(data != null)
((FormData) data).flushCache();
return true;
}//flushCache()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Rectangle rect = composite.getClientArea();
int x = rect.x + marginLeft + marginWidth;
int y = rect.y + marginTop + marginHeight;
int width = Math.max(0, rect.width - marginLeft - 2 * marginWidth - marginRight);
int height = Math.max(0, rect.height - marginTop - 2 * marginHeight - marginBottom);
layout(composite, true, x, y, width, height, flushCache);
}//layout()//
/**
* Lays out the composite.
* @param composite
* @param move
* @param x
* @param y
* @param width
* @param height
* @param flushCache
* @return The size of the composite.
*/
Point layout(Composite composite, boolean move, int x, int y, int width, int height, boolean flushCache) {
Control[] children = composite.getChildren();
int count = 0;
IOverlay[] overlayChildren = new IOverlay[children.length];
int overlayCount = 0;
for(int index = 0; index < children.length; index++) {
if(children[index] instanceof IOverlay) {
overlayChildren[overlayCount++] = (IOverlay) children[index];
}//if//
else {
Control child = children[index];
FormData data = (FormData) child.getLayoutData();
if(data == null) {
child.setLayoutData(data = new FormData());
}//if//
if(flushCache) {
data.flushCache();
}//if//
data.cacheLeft = data.cacheRight = data.cacheTop = data.cacheBottom = null;
children[count++] = children[index];
}//else//
}//for//
boolean[] flush = null;
Rectangle[] area = null;
int w = 0;
int h = 0;
for(int i = 0; i < count; i++) {
Control child = children[i];
FormData data = (FormData) child.getLayoutData();
//Declarative Engineering: Set invisible children to have no size.//
if(!child.getVisible()) {
if(move) {
if(area == null) {
area = new Rectangle[count];
}//if//
area[i] = new Rectangle(0, 0, 0, 0);
area[i].x = x + data.getLeftAttachment(child, spacing, flushCache).solveX(width);
area[i].width = 0;
}//if//
}//if//
else {
if(width != SWT.DEFAULT) {
data.needed = false;
FormAttachment left = data.getLeftAttachment(child, spacing, flushCache);
FormAttachment right = data.getRightAttachment(child, spacing, flushCache);
int x1 = left.solveX(width);
int x2 = right.solveX(width);
if(data.height == SWT.DEFAULT && !data.needed) {
int trim = 0;
//TEMPORARY CODE
if(child instanceof Scrollable) {
Rectangle rect = ((Scrollable) child).computeTrim(0, 0, 0, 0);
trim = rect.width;
}//if//
else {
trim = child.getBorderWidth() * 2;
}//else//
data.cacheWidth = data.cacheHeight = -1;
int currentWidth = Math.max(0, x2 - x1 - trim);
data.computeSize(child, currentWidth, data.height, flushCache);
if(flush == null) {
flush = new boolean[count];
}//if//
flush[i] = true;
}//if//
w = Math.max(x2, w);
if(move) {
if(area == null) {
area = new Rectangle[count];
}//if//
area[i] = new Rectangle(0, 0, 0, 0);
area[i].x = x + x1;
area[i].width = x2 - x1;
}//if//
}//if//
else {
w = Math.max(computeWidth(child, data, flushCache), w);
}//else//
}//else//
}//for//
for(int i = 0; i < count; i++) {
Control child = children[i];
FormData data = (FormData) child.getLayoutData();
//Declarative Engineering: Set invisible children to have no size.//
if(!child.getVisible()) {
if(move) {
area[i].y = data.getTopAttachment(child, spacing, flushCache).solveX(height);
area[i].height = 0;
}//if//
}//if//
else {
if(height != SWT.DEFAULT) {
int y1 = data.getTopAttachment(child, spacing, flushCache).solveX(height);
int y2 = data.getBottomAttachment(child, spacing, flushCache).solveX(height);
h = Math.max(y2, h);
if(move) {
area[i].y = y + y1;
area[i].height = y2 - y1;
}//if//
}//if//
else {
h = Math.max(computeHeight(child, data, flushCache), h);
}//else//
}//else//
}//for//
for(int i = 0; i < count; i++) {
Control child = children[i];
FormData data = (FormData) child.getLayoutData();
if(flush != null && flush[i]) {
data.cacheWidth = data.cacheHeight = -1;
}//if//
data.cacheLeft = data.cacheRight = data.cacheTop = data.cacheBottom = null;
}//for//
if(move) {
for(int i = 0; i < count; i++) {
children[i].setBounds(area[i]);
}//for//
}//if//
w += marginLeft + marginWidth * 2 + marginRight;
h += marginTop + marginHeight * 2 + marginBottom;
if(overlayCount > 0) { //Declarative Engineering: Layout the overlays.//
int upperLeftOffset = 0;
int upperRightOffset = 0;
int lowerLeftOffset = 0;
int lowerRightOffset = 0;
Control lastPeer = null;
Arrays.sort(overlayChildren, 0, overlayCount, new Comparator() {
public int compare(Object arg0, Object arg1) {
return ((IOverlay) arg0).getPeerControl().hashCode() - ((IOverlay) arg1).getPeerControl().hashCode();
}//compare()//
});
for(int index = 0; index < overlayCount; index++) {
IOverlay overlay = overlayChildren[index];
Control peer = overlay.getPeerControl();
Rectangle bounds = peer.getBounds();
Point size = overlay.getSize();
if(peer != lastPeer) {
upperLeftOffset = 0;
upperRightOffset = 0;
lowerLeftOffset = 0;
lowerRightOffset = 0;
lastPeer = peer;
}//if//
switch(overlay.getPosition()) {
case IOverlay.POSITION_UPPER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + upperLeftOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperLeftOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_UPPER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - upperRightOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - lowerRightOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + lowerLeftOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerLeftOffset += bounds.width + 1;
break;
}//case//
}//switch//
((Control) overlay).setBounds(bounds);
}//for//
}//block//
return new Point(w, h);
}//layout()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
String string = "FormLayout {";
if(marginWidth != 0)
string += "marginWidth=" + marginWidth + " ";
if(marginHeight != 0)
string += "marginHeight=" + marginHeight + " ";
if(marginLeft != 0)
string += "marginLeft=" + marginLeft + " ";
if(marginRight != 0)
string += "marginRight=" + marginRight + " ";
if(marginTop != 0)
string += "marginTop=" + marginTop + " ";
if(marginBottom != 0)
string += "marginBottom=" + marginBottom + " ";
if(spacing != 0)
string += "spacing=" + spacing + " ";
string = string.trim();
string += "}";
return string;
}//toString()//
}//FormLayout//

View File

@@ -0,0 +1,619 @@
/*
* Copyright (c) 2000, 2006 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
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* <code>GridData</code> is the layout data object associated with
* <code>GridLayout</code>. To set a <code>GridData</code> object into a
* control, you use the <code>Control.setLayoutData(Object)</code> method.
* <p>
* There are two ways to create a <code>GridData</code> object with certain
* fields set. The first is to set the fields directly, like this:
* <pre>
* GridData gridData = new GridData();
* gridData.horizontalAlignment = GridData.FILL;
* gridData.grabExcessHorizontalSpace = true;
* button1.setLayoutData(gridData);
* </pre>
* The second is to take advantage of convenience style bits defined
* by <code>GridData</code>:
* <pre>
* button1.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
* </pre>
* </p>
* <p>
* NOTE: Do not reuse <code>GridData</code> objects. Every control in a
* <code>Composite</code> that is managed by a <code>GridLayout</code>
* must have a unique <code>GridData</code> object. If the layout data
* for a control in a <code>GridLayout</code> is null at layout time,
* a unique <code>GridData</code> object is created for it.
* </p>
*
* @see GridLayout
* @see Control#setLayoutData
*/
public final class GridData {
/**
* verticalAlignment specifies how controls will be positioned
* vertically within a cell.
*
* The default value is CENTER.
*
* Possible values are: <ul>
* <li>SWT.BEGINNING (or SWT.TOP): Position the control at the top of the cell</li>
* <li>SWT.CENTER: Position the control in the vertical center of the cell</li>
* <li>SWT.END (or SWT.BOTTOM): Position the control at the bottom of the cell</li>
* <li>SWT.FILL: Resize the control to fill the cell vertically</li>
* </ul>
*/
public int verticalAlignment = CENTER;
/**
* horizontalAlignment specifies how controls will be positioned
* horizontally within a cell.
*
* The default value is BEGINNING.
*
* Possible values are: <ul>
* <li>SWT.BEGINNING (or SWT.LEFT): Position the control at the left of the cell</li>
* <li>SWT.CENTER: Position the control in the horizontal center of the cell</li>
* <li>SWT.END (or SWT.RIGHT): Position the control at the right of the cell</li>
* <li>SWT.FILL: Resize the control to fill the cell horizontally</li>
* </ul>
*/
public int horizontalAlignment = BEGINNING;
/**
* widthHint specifies the preferred width in pixels. This value
* is the wHint passed into Control.computeSize(int, int, boolean)
* to determine the preferred size of the control.
*
* The default value is SWT.DEFAULT.
*
* @see Control#computeSize(int, int, boolean)
*/
public int widthHint = SWT.DEFAULT;
/**
* heightHint specifies the preferred height in pixels. This value
* is the hHint passed into Control.computeSize(int, int, boolean)
* to determine the preferred size of the control.
*
* The default value is SWT.DEFAULT.
*
* @see Control#computeSize(int, int, boolean)
*/
public int heightHint = SWT.DEFAULT;
/**
* horizontalIndent specifies the number of pixels of indentation
* that will be placed along the left side of the cell.
*
* The default value is 0.
*/
public int horizontalIndent = 0;
/**
* verticalIndent specifies the number of pixels of indentation
* that will be placed along the top side of the cell.
*
* The default value is 0.
*
* @since 3.1
*/
public int verticalIndent = 0;
/**
* horizontalSpan specifies the number of column cells that the control
* will take up.
*
* The default value is 1.
*/
public int horizontalSpan = 1;
/**
* verticalSpan specifies the number of row cells that the control
* will take up.
*
* The default value is 1.
*/
public int verticalSpan = 1;
/**
* <p>grabExcessHorizontalSpace specifies whether the width of the cell
* changes depending on the size of the parent Composite. If
* grabExcessHorizontalSpace is <code>true</code>, the following rules
* apply to the width of the cell:</p>
* <ul>
* <li>If extra horizontal space is available in the parent, the cell will
* grow to be wider than its preferred width. The new width
* will be "preferred width + delta" where delta is the extra
* horizontal space divided by the number of grabbing columns.</li>
* <li>If there is not enough horizontal space available in the parent, the
* cell will shrink until it reaches its minimum width as specified by
* GridData.minimumWidth. The new width will be the maximum of
* "minimumWidth" and "preferred width - delta", where delta is
* the amount of space missing divided by the number of grabbing columns.</li>
* <li>If the parent is packed, the cell will be its preferred width
* as specified by GridData.widthHint.</li>
* <li>If the control spans multiple columns and there are no other grabbing
* controls in any of the spanned columns, the last column in the span will
* grab the extra space. If there is at least one other grabbing control
* in the span, the grabbing will be spread over the columns already
* marked as grabExcessHorizontalSpace.</li>
* </ul>
*
* <p>The default value is false.</p>
*
* @see GridData#minimumWidth
* @see GridData#widthHint
*/
public boolean grabExcessHorizontalSpace = false;
/**
* <p>grabExcessVerticalSpace specifies whether the height of the cell
* changes depending on the size of the parent Composite. If
* grabExcessVerticalSpace is <code>true</code>, the following rules
* apply to the height of the cell:</p>
* <ul>
* <li>If extra vertical space is available in the parent, the cell will
* grow to be taller than its preferred height. The new height
* will be "preferred height + delta" where delta is the extra
* vertical space divided by the number of grabbing rows.</li>
* <li>If there is not enough vertical space available in the parent, the
* cell will shrink until it reaches its minimum height as specified by
* GridData.minimumHeight. The new height will be the maximum of
* "minimumHeight" and "preferred height - delta", where delta is
* the amount of space missing divided by the number of grabbing rows.</li>
* <li>If the parent is packed, the cell will be its preferred height
* as specified by GridData.heightHint.</li>
* <li>If the control spans multiple rows and there are no other grabbing
* controls in any of the spanned rows, the last row in the span will
* grab the extra space. If there is at least one other grabbing control
* in the span, the grabbing will be spread over the rows already
* marked as grabExcessVerticalSpace.</li>
* </ul>
*
* <p>The default value is false.</p>
*
* @see GridData#minimumHeight
* @see GridData#heightHint
*/
public boolean grabExcessVerticalSpace = false;
/**
* <p>TODO: This should really default to -1, and a value of -1 should be using the control's minimum. Currently 0 or -1 uses the control's minimum, but not for the layout - only for reporting a total minimum for the layout.</p>
* minimumWidth specifies the minimum width in pixels. This value
* applies only if grabExcessHorizontalSpace is true. A value of
* SWT.DEFAULT means that the minimum width will be the result
* of Control.computeSize(int, int, boolean) where wHint is
* determined by GridData.widthHint.
*
* The default value is 0.
*
* @since 3.1
* @see Control#computeSize(int, int, boolean)
* @see GridData#widthHint
*/
public int minimumWidth = 0;
/**
* <p>TODO: This should really default to -1, and a value of -1 should be using the control's minimum. Currently 0 or -1 uses the control's minimum, but not for the layout - only for reporting a total minimum for the layout.</p>
* minimumHeight specifies the minimum height in pixels. This value
* applies only if grabExcessVerticalSpace is true. A value of
* SWT.DEFAULT means that the minimum height will be the result
* of Control.computeSize(int, int, boolean) where hHint is
* determined by GridData.heightHint.
*
* The default value is 0.
*
* @since 3.1
* @see Control#computeSize(int, int, boolean)
* @see GridData#heightHint
*/
public int minimumHeight = 0;
/**
* exclude informs the layout to ignore this control when sizing
* and positioning controls. If this value is <code>true</code>,
* the size and position of the control will not be managed by the
* layout. If this value is <code>false</code>, the size and
* position of the control will be computed and assigned.
*
* The default value is <code>false</code>.
*
* @since 3.1
*/
public boolean exclude = false;
/**
* Value for horizontalAlignment or verticalAlignment.
* Position the control at the top or left of the cell.
* Not recommended. Use SWT.BEGINNING, SWT.TOP or SWT.LEFT instead.
*/
public static final int BEGINNING = SWT.BEGINNING;
/**
* Value for horizontalAlignment or verticalAlignment.
* Position the control in the vertical or horizontal center of the cell
* Not recommended. Use SWT.CENTER instead.
*/
public static final int CENTER = 2;
/**
* Value for horizontalAlignment or verticalAlignment.
* Position the control at the bottom or right of the cell
* Not recommended. Use SWT.END, SWT.BOTTOM or SWT.RIGHT instead.
*/
public static final int END = 3;
/**
* Value for horizontalAlignment or verticalAlignment.
* Resize the control to fill the cell horizontally or vertically.
* Not recommended. Use SWT.FILL instead.
*/
public static final int FILL = SWT.FILL;
/**
* Style bit for <code>new GridData(int)</code>.
* Position the control at the top of the cell.
* Not recommended. Use
* <code>new GridData(int, SWT.BEGINNING, boolean, boolean)</code>
* instead.
*/
public static final int VERTICAL_ALIGN_BEGINNING = 1 << 1;
/**
* Style bit for <code>new GridData(int)</code> to position the
* control in the vertical center of the cell.
* Not recommended. Use
* <code>new GridData(int, SWT.CENTER, boolean, boolean)</code>
* instead.
*/
public static final int VERTICAL_ALIGN_CENTER = 1 << 2;
/**
* Style bit for <code>new GridData(int)</code> to position the
* control at the bottom of the cell.
* Not recommended. Use
* <code>new GridData(int, SWT.END, boolean, boolean)</code>
* instead.
*/
public static final int VERTICAL_ALIGN_END = 1 << 3;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fill the cell vertically.
* Not recommended. Use
* <code>new GridData(int, SWT.FILL, boolean, boolean)</code>
* instead
*/
public static final int VERTICAL_ALIGN_FILL = 1 << 4;
/**
* Style bit for <code>new GridData(int)</code> to position the
* control at the left of the cell.
* Not recommended. Use
* <code>new GridData(SWT.BEGINNING, int, boolean, boolean)</code>
* instead.
*/
public static final int HORIZONTAL_ALIGN_BEGINNING = 1 << 5;
/**
* Style bit for <code>new GridData(int)</code> to position the
* control in the horizontal center of the cell.
* Not recommended. Use
* <code>new GridData(SWT.CENTER, int, boolean, boolean)</code>
* instead.
*/
public static final int HORIZONTAL_ALIGN_CENTER = 1 << 6;
/**
* Style bit for <code>new GridData(int)</code> to position the
* control at the right of the cell.
* Not recommended. Use
* <code>new GridData(SWT.END, int, boolean, boolean)</code>
* instead.
*/
public static final int HORIZONTAL_ALIGN_END = 1 << 7;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fill the cell horizontally.
* Not recommended. Use
* <code>new GridData(SWT.FILL, int, boolean, boolean)</code>
* instead.
*/
public static final int HORIZONTAL_ALIGN_FILL = 1 << 8;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fit the remaining horizontal space.
* Not recommended. Use
* <code>new GridData(int, int, true, boolean)</code>
* instead.
*/
public static final int GRAB_HORIZONTAL = 1 << 9;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fit the remaining vertical space.
* Not recommended. Use
* <code>new GridData(int, int, boolean, true)</code>
* instead.
*/
public static final int GRAB_VERTICAL = 1 << 10;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fill the cell vertically and to fit the remaining
* vertical space.
* FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL
* Not recommended. Use
* <code>new GridData(int, SWT.FILL, boolean, true)</code>
* instead.
*/
public static final int FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fill the cell horizontally and to fit the remaining
* horizontal space.
* FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL
* Not recommended. Use
* <code>new GridData(SWT.FILL, int, true, boolean)</code>
* instead.
*/
public static final int FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fill the cell horizontally and vertically and
* to fit the remaining horizontal and vertical space.
* FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL
* Not recommended. Use
* <code>new GridData(SWT.FILL, SWT.FILL, true, true)</code>
* instead.
*/
public static final int FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL;
int cacheWidth = -1;
int cacheHeight = -1;
int defaultWhint;
int defaultHhint;
int defaultWidth = -1;
int defaultHeight = -1;
int currentWhint;
int currentHhint;
int currentWidth = -1;
int currentHeight = -1;
//Declarative Engineering//
int cacheHSpan = -1;
int cacheVSpan = -1;
/**
* Constructs a new instance of GridData using default values.
*/
public GridData() {
super();
}//GridData()//
/**
* Constructs a new instance based on the GridData style.
* This constructor is not recommended.
*
* @param style the GridData style
*/
public GridData(int style) {
super();
if((style & VERTICAL_ALIGN_BEGINNING) != 0)
verticalAlignment = BEGINNING;
if((style & VERTICAL_ALIGN_CENTER) != 0)
verticalAlignment = CENTER;
if((style & VERTICAL_ALIGN_FILL) != 0)
verticalAlignment = FILL;
if((style & VERTICAL_ALIGN_END) != 0)
verticalAlignment = END;
if((style & HORIZONTAL_ALIGN_BEGINNING) != 0)
horizontalAlignment = BEGINNING;
if((style & HORIZONTAL_ALIGN_CENTER) != 0)
horizontalAlignment = CENTER;
if((style & HORIZONTAL_ALIGN_FILL) != 0)
horizontalAlignment = FILL;
if((style & HORIZONTAL_ALIGN_END) != 0)
horizontalAlignment = END;
grabExcessHorizontalSpace = (style & GRAB_HORIZONTAL) != 0;
grabExcessVerticalSpace = (style & GRAB_VERTICAL) != 0;
}//GridData()//
/**
* Constructs a new instance of GridData according to the parameters.
*
* @param horizontalAlignment how control will be positioned horizontally within a cell
* @param verticalAlignment how control will be positioned vertically within a cell
* @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
* @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
*
* @since 3.0
*/
public GridData(int horizontalAlignment, int verticalAlignment, boolean grabExcessHorizontalSpace, boolean grabExcessVerticalSpace) {
this(horizontalAlignment, verticalAlignment, grabExcessHorizontalSpace, grabExcessVerticalSpace, 1, 1);
}//GridData()//
/**
* Constructs a new instance of GridData according to the parameters.
*
* @param horizontalAlignment how control will be positioned horizontally within a cell
* @param verticalAlignment how control will be positioned vertically within a cell
* @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
* @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
* @param horizontalSpan the number of column cells that the control will take up
* @param verticalSpan the number of row cells that the control will take up
*
* @since 3.0
*/
public GridData(int horizontalAlignment, int verticalAlignment, boolean grabExcessHorizontalSpace, boolean grabExcessVerticalSpace, int horizontalSpan, int verticalSpan) {
super();
this.horizontalAlignment = horizontalAlignment;
this.verticalAlignment = verticalAlignment;
this.grabExcessHorizontalSpace = grabExcessHorizontalSpace;
this.grabExcessVerticalSpace = grabExcessVerticalSpace;
this.horizontalSpan = horizontalSpan;
this.verticalSpan = verticalSpan;
}//GridData()//
/**
* Computes the size of given control, described by this grid data.
* @param control The control referencing this grid data.
* @param wHint The width hint.
* @param hHint The height hint.
* @param flushCache Whether to flush the cache.
*/
void computeSize(Control control, int wHint, int hHint, boolean flushCache) {
if(cacheWidth == -1 || cacheHeight == -1) {
if(wHint == this.widthHint && hHint == this.heightHint) {
if(defaultWidth == -1 || defaultHeight == -1 || wHint != defaultWhint || hHint != defaultHhint) {
Point size = control.computeSize(wHint, hHint, flushCache);
defaultWhint = wHint;
defaultHhint = hHint;
defaultWidth = size.x;
defaultHeight = size.y;
}//if//
cacheWidth = defaultWidth;
cacheHeight = defaultHeight;
return;
}//if//
if(currentWidth == -1 || currentHeight == -1 || wHint != currentWhint || hHint != currentHhint) {
Point size = control.computeSize(wHint, hHint, flushCache);
currentWhint = wHint;
currentHhint = hHint;
currentWidth = size.x;
currentHeight = size.y;
}//if//
cacheWidth = currentWidth;
cacheHeight = currentHeight;
}//if//
}//computeSize()//
/**
* Clears any cached values.
*/
void flushCache() {
cacheWidth = cacheHeight = -1;
defaultWidth = defaultHeight = -1;
currentWidth = currentHeight = -1;
}//flushCache()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
String hAlign = "";
String vAlign = "";
String string;
switch(horizontalAlignment) {
case SWT.FILL:
hAlign = "SWT.FILL";
break;
case SWT.BEGINNING:
hAlign = "SWT.BEGINNING";
break;
case SWT.LEFT:
hAlign = "SWT.LEFT";
break;
case SWT.END:
hAlign = "SWT.END";
break;
case END:
hAlign = "GridData.END";
break;
case SWT.RIGHT:
hAlign = "SWT.RIGHT";
break;
case SWT.CENTER:
hAlign = "SWT.CENTER";
break;
case CENTER:
hAlign = "GridData.CENTER";
break;
default:
hAlign = "Undefined " + horizontalAlignment;
break;
}//switch//
switch(verticalAlignment) {
case SWT.FILL:
vAlign = "SWT.FILL";
break;
case SWT.BEGINNING:
vAlign = "SWT.BEGINNING";
break;
case SWT.TOP:
vAlign = "SWT.TOP";
break;
case SWT.END:
vAlign = "SWT.END";
break;
case END:
vAlign = "GridData.END";
break;
case SWT.BOTTOM:
vAlign = "SWT.BOTTOM";
break;
case SWT.CENTER:
vAlign = "SWT.CENTER";
break;
case CENTER:
vAlign = "GridData.CENTER";
break;
default:
vAlign = "Undefined " + verticalAlignment;
break;
}//switch//
string = "GridData {horizontalAlignment: " + hAlign + " ";
if(horizontalIndent != 0)
string += "horizontalIndent=" + horizontalIndent + " ";
if(horizontalSpan != 1)
string += "horizontalSpan=" + horizontalSpan + " ";
if(grabExcessHorizontalSpace)
string += "grabExcessHorizontalSpace=" + grabExcessHorizontalSpace + " ";
if(widthHint != SWT.DEFAULT)
string += "widthHint=" + widthHint + " ";
if(minimumWidth != 0)
string += "minimumWidth=" + minimumWidth + " ";
string += "verticalAlignment=" + vAlign + " ";
if(verticalIndent != 0)
string += "verticalIndent=" + verticalIndent + " ";
if(verticalSpan != 1)
string += "verticalSpan=" + verticalSpan + " ";
if(grabExcessVerticalSpace)
string += "grabExcessVerticalSpace=" + grabExcessVerticalSpace + " ";
if(heightHint != SWT.DEFAULT)
string += "heightHint=" + heightHint + " ";
if(minimumHeight != 0)
string += "minimumHeight=" + minimumHeight + " ";
if(exclude)
string += "exclude=" + exclude + " ";
string = string.trim();
string += "}";
return string;
}//toString()//
}//GridData//

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* The layout base class.
*/
public abstract class Layout extends org.eclipse.swt.widgets.Layout {
/**
* Layout constructor.
*/
public Layout() {
}//Layout()//
/**
* Computes the current size of the composite using this layout.
* @param composite The composite that uses this layout.
* @return The current size of the composite.
*/
public Point computeCurrentSize(Composite composite) {
Point result = new Point(0, 0);
Control[] children = composite.getChildren();
//Note: This works well, but doesn't account for bottom and right margins. Subclasses can overload this to add the margins.//
for(int i = 0; i < children.length; i++) {
Rectangle rect = children[i].getBounds();
if(children[i].isVisible()) {
result.x = Math.max(result.x, rect.x + rect.width);
result.y = Math.max(result.y, rect.y + rect.height);
}//if//
}//for//
return result;
}//computeCurrentSize()//
}//Layout//

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt.layout;
/**
* The base class for all layout data types.
*/
public abstract class LayoutData {
/**
* LayoutData constructor.
*/
public LayoutData() {
}//LayoutData()//
/**
* Flushes any cached data.
* This should be called when ever the component with the layout data changes state in such a way as to invalidate a previous layout of the component.
*/
public abstract void flushCache();
}//LayoutData//

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2000, 2006 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
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
/**
* Each control controlled by a <code>RowLayout</code> can have its initial width and height specified by setting a <code>RowData</code> object into the control.
* <p>
* The following code uses a <code>RowData</code> object to change the initial size of a <code>Button</code> in a <code>Shell</code>:
* <pre>
* Display display = new Display();
* Shell shell = new Shell(display);
* shell.setLayout(new RowLayout());
* Button button1 = new Button(shell, SWT.PUSH);
* button1.setText("Button 1");
* button1.setLayoutData(new RowData(50, 40));
* </pre>
* </p>
* @see RowLayout
*/
public final class RowData {
/** Specifies the desired width in pixels. This value is the wHint passed into Control.computeSize(int, int, boolean) to determine the preferred size of the control. */
public int width = SWT.DEFAULT;
/** Specifies the preferred height in pixels. This value is the hHint passed into Control.computeSize(int, int, boolean) to determine the preferred size of the control. */
public int height = SWT.DEFAULT;
/** Informs the layout to ignore this control when sizing and positioning controls. If this value is <code>true</code>, the size and position of the control will not be managed by the layout. If this value is <code>false</code>, the size and position of the control will be computed and assigned. */
public boolean exclude = false;
//TODO: Utilize the minimums... add them to the cml's
/** The minimum width. If the row data describes a composite and this value is >= zero, this will override the composite's calculated minimum. */
public int minimumWidth = -1;
/** The minimum height. If the row data describes a composite and this value is >= zero, this will override the composite's calculated minimum. */
public int minimumHeight = -1;
/** The alignment of the widget opposite the row layout's type (direction). A value of NONE will follow the layout's alignment. */
public int alignment = SWT.NONE;
/**
* Constructs a new instance of RowData using
* default values.
*/
public RowData() {
}//RowData()//
/**
* Constructs a new instance of RowData according to the parameters.
* A value of SWT.DEFAULT indicates that no minimum width or
* no minimum height is specified.
*
* @param width a minimum width for the control
* @param height a minimum height for the control
*/
public RowData(int width, int height) {
this.width = width;
this.height = height;
}//RowData()//
/**
* Constructs a new instance of RowData according to the parameter.
* A value of SWT.DEFAULT indicates that no minimum width or
* no minimum height is specified.
*
* @param point a point whose x coordinate specifies a minimum width for the control
* and y coordinate specifies a minimum height for the control
*/
public RowData(Point point) {
this(point.x, point.y);
}//RowData()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
String string = "RowData {";
if(width != SWT.DEFAULT)
string += "width=" + width + " ";
if(height != SWT.DEFAULT)
string += "height=" + height + " ";
if(exclude)
string += "exclude=" + exclude + " ";
string = string.trim();
string += "}";
return string;
}//toString()//
}//RowData//

View File

@@ -0,0 +1,822 @@
/*
* Copyright (c) 2000, 2006 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
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import com.common.debug.Debug;
import com.foundation.view.swt.IOverlay;
/**
* Instances of this class determine the size and position of the
* children of a <code>Composite</code> by placing them either in
* horizontal rows or vertical columns within the parent <code>Composite</code>.
* <p>
* <code>RowLayout</code> aligns all controls in one row if the
* <code>type</code> is set to horizontal, and one column if it is
* set to vertical. It has the ability to wrap, and provides configurable
* margins and spacing. <code>RowLayout</code> has a number of configuration
* fields. In addition, the height and width of each control in a
* <code>RowLayout</code> can be specified by setting a <code>RowData</code>
* object into the control using <code>setLayoutData ()</code>.
* </p>
* <p>
* The following example code creates a <code>RowLayout</code>, sets all
* of its fields to non-default values, and then sets it into a
* <code>Shell</code>.
* <pre>
* RowLayout rowLayout = new RowLayout();
* rowLayout.wrap = false;
* rowLayout.pack = false;
* rowLayout.justify = true;
* rowLayout.type = SWT.VERTICAL;
* rowLayout.marginLeft = 5;
* rowLayout.marginTop = 5;
* rowLayout.marginRight = 5;
* rowLayout.marginBottom = 5;
* rowLayout.spacing = 0;
* shell.setLayout(rowLayout);
* </pre>
* If you are using the default field values, you only need one line of code:
* <pre>
* shell.setLayout(new RowLayout());
* </pre>
* </p>
*
* @see RowData
*/
public final class RowLayout extends Layout {
/** Specifies whether the layout places controls in rows or columns. Possible values are: <ul><li>HORIZONTAL: Position the controls horizontally from left to right</li><li>VERTICAL: Position the controls vertically from top to bottom</li></ul> */
public int type = SWT.HORIZONTAL;
/** Specifies the number of pixels of horizontal margin that will be placed along the left and right edges of the layout. */
public int marginWidth = 0;
/** Specifies the number of pixels of vertical margin that will be placed along the top and bottom edges of the layout. */
public int marginHeight = 0;
/** Specifies the number of pixels between the edge of one cell and the edge of its neighbouring cell. */
public int spacing = 3;
/** Specifies whether a control will be wrapped to the next row if there is insufficient space on the current row. */
public boolean wrap = true;
/** Specifies whether all controls in the layout take their preferred size. If pack is false, all controls will have the same size which is the size required to accommodate the largest preferred height and the largest preferred width of all the controls in the layout. */
public boolean pack = true;
/** Specifies a default alignment for all controls in the axis opposite the type (direction). */
public int alignment = SWT.BEGINNING;
/** Specifies whether the controls in a row should be fully justified, with any extra space placed between the controls. */
public boolean justify = false;
/** Specifies the number of pixels of horizontal margin that will be placed along the left edge of the layout. */
public int marginLeft = 3;
/** Specifies the number of pixels of vertical margin that will be placed along the top edge of the layout. */
public int marginTop = 3;
/** Specifies the number of pixels of horizontal margin that will be placed along the right edge of the layout. */
public int marginRight = 3;
/** Specifies the number of pixels of vertical margin that will be placed along the bottom edge of the layout. */
public int marginBottom = 3;
/**
* Constructs a new instance of this class.
*/
public RowLayout() {
}//RowLayout()//
/**
* Constructs a new instance of this class given the type.
* @param type the type of row layout
*/
public RowLayout(int type) {
this.type = type;
}//RowLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeCurrentSize(org.eclipse.swt.widgets.Composite)
*/
public Point computeCurrentSize(Composite composite) {
Point result = super.computeCurrentSize(composite);
result.x += marginRight + marginWidth;
result.y += marginBottom + marginHeight;
return result;
}//computeCurrentSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
Point extent;
if(type == SWT.HORIZONTAL) {
extent = layoutHorizontal(composite, false, (wHint != SWT.DEFAULT) && wrap, wHint, flushCache);
}//if//
else {
extent = layoutVertical(composite, false, (hHint != SWT.DEFAULT) && wrap, hHint, flushCache);
}//else//
if(wHint != SWT.DEFAULT)
extent.x = wHint;
if(hHint != SWT.DEFAULT)
extent.y = hHint;
return extent;
}//computeSize()//
/**
* @param control
* @param flushCache
* @return
*/
Point computeSize(Control control, boolean flushCache) {
int wHint = SWT.DEFAULT, hHint = SWT.DEFAULT;
RowData data = (RowData) control.getLayoutData();
if(data != null) {
wHint = data.width;
hHint = data.height;
}//if//
return control.computeSize(wHint, hHint, flushCache);
}//computeSize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#flushCache(org.eclipse.swt.widgets.Control)
*/
public boolean flushCache(Control control) {
return true;
}//flushCache()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Rectangle clientArea = composite.getClientArea();
if(type == SWT.HORIZONTAL) {
layoutHorizontal(composite, true, wrap, clientArea.width, flushCache);
}//if//
else {
layoutVertical(composite, true, wrap, clientArea.height, flushCache);
}//else//
}//layout()//
/**
* @param composite
* @param move
* @param wrap
* @param width
* @param flushCache
* @return
*/
Point layoutHorizontal(Composite composite, boolean move, boolean wrap, int width, boolean flushCache) {
Control[] children = composite.getChildren();
int count = 0; //The child count.//
Control[] excluded = null;
int nextExcludedIndex = 0;
IOverlay[] overlayChildren = new IOverlay[children.length];
int overlayCount = 0;
int childWidth = 0;
int childHeight = 0;
int maxHeight = 0;
int clientX = 0;
int clientY = 0;
int[] wraps = null;
boolean wrapped = false;
Rectangle[] rectangle = null;
int maxX = 0;
int x = marginLeft + marginWidth;
int y = marginTop + marginHeight;
int availableHeight = composite.getClientArea().height;
//Declarative Engineering//
//Moved above the following for loop in order to include invisible children (which may become visible later - we don't want the layout to change all the sizes of the components if they do become visible).//
//Modified to exclude the specifically excluded controls.//
for(int index = 0; index < children.length; index++) {
Control child = children[index];
RowData data = (RowData) child.getLayoutData();
//Ignore excluded and overlay controls.//
if(data == null || (!data.exclude && !(child instanceof IOverlay))) {
Point size = computeSize(child, flushCache);
childWidth = Math.max(childWidth, size.x);
childHeight = Math.max(childHeight, size.y);
}//if//
}//for//
maxHeight = childHeight;
//Iterate over the controls and remove any that are not visible or excluded, and move any that are overlay controls into another collection.//
for(int index = 0; index < children.length; index++) {
Control child = children[index];
RowData data = (RowData) child.getLayoutData();
if(child instanceof IOverlay) {
overlayChildren[overlayCount++] = (IOverlay) children[index];
}//if//
else if(data != null && data.exclude) {
if(excluded == null) {
int excludeCount = 1;
for(int i = index + 1; i < children.length; i++) {
RowData childData = (RowData) children[i].getLayoutData();
if(childData != null && childData.exclude) {
excludeCount++;
}//if//
}//for//
excluded = new Control[excludeCount];
}//if//
excluded[nextExcludedIndex++] = children[index];
}//else if//
else if(child.getVisible()) {
children[count++] = children[index];
}//else if//
}//for//
if(move) {
Rectangle rect = composite.getClientArea();
clientX = rect.x;
clientY = rect.y;
}//if//
if(move && justify) {
rectangle = new Rectangle[count];
wraps = new int[count];
}//if//
availableHeight = Math.max(maxHeight, availableHeight);
for(int i = 0; i < count; i++) {
Control child = children[i];
RowData data = (RowData) child.getLayoutData();
if(pack) {
Point size = computeSize(child, flushCache);
childWidth = size.x;
childHeight = size.y;
}//if//
if(wrap && (i != 0) && (x + childWidth > width)) {
wrapped = true;
if(move && justify) {
wraps[i - 1] = maxHeight;
}//if//
x = marginLeft + marginWidth;
y += spacing + maxHeight;
if(pack) {
maxHeight = 0;
}//if//
}//if//
if(move) {
int childX = x + clientX;
int childY = y + clientY;
switch(data == null || data.alignment == SWT.NONE ? alignment : data.alignment) {
case SWT.FILL: {
childHeight = availableHeight - (marginBottom + marginTop + marginHeight);
break;
}//case//
case SWT.END: {
childY += availableHeight - (childHeight + marginBottom + marginTop + marginHeight);
break;
}//case//
case SWT.CENTER: {
childY += ((availableHeight - (childHeight + marginBottom + marginTop + marginHeight)) >> 1);
break;
}//case//
}//switch//
if(justify) {
rectangle[i] = new Rectangle(childX, childY, childWidth, childHeight);
}//if//
else {
child.setBounds(childX, childY, childWidth, childHeight);
}//else//
}//if//
x += spacing + childWidth;
maxX = Math.max(maxX, x);
}//for//
maxX = Math.max(clientX + marginLeft + marginWidth, maxX - spacing);
if(!wrapped) {
maxX += marginRight + marginWidth;
}//if//
if(move && justify) {
int space = 0, margin = 0;
if(!wrapped) {
space = Math.max(0, (width - maxX) / (count + 1));
margin = Math.max(0, ((width - maxX) % (count + 1)) / 2);
}//if//
else {
int last = 0;
if(count > 0) {
wraps[count - 1] = maxHeight;
}//if//
for(int i = 0; i < count; i++) {
if(wraps[i] != 0) {
int wrapCount = i - last + 1;
int wrapX = 0;
for(int j = last; j <= i; j++) {
wrapX += rectangle[j].width + spacing;
}//for//
space = Math.max(0, (width - wrapX) / (wrapCount + 1));
margin = Math.max(0, ((width - wrapX) % (wrapCount + 1)) / 2);
for(int j = last; j <= i; j++) {
rectangle[j].x += (space * (j - last + 1)) + margin;
}//for//
last = i + 1;
}//if//
}//for//
}//else//
for(int i = 0; i < count; i++) {
if(!wrapped) {
rectangle[i].x += (space * (i + 1)) + margin;
}//if//
children[i].setBounds(rectangle[i]);
}//for//
}//if//
//Layout the overlays.//
for(int index = 0; index < overlayCount; index++) {
IOverlay overlay = overlayChildren[index];
Control peer = overlay.getPeerControl();
Rectangle bounds = peer.getBounds();
Point size = overlay.getSize();
switch(overlay.getPosition()) {
case IOverlay.POSITION_UPPER_LEFT: {
bounds.x += overlay.getHorizontalOffset();
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
break;
}//case//
case IOverlay.POSITION_UPPER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
break;
}//case//
case IOverlay.POSITION_LOWER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
break;
}//case//
case IOverlay.POSITION_LOWER_LEFT: {
bounds.x += overlay.getHorizontalOffset();
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
break;
}//case//
}//switch//
((Control) overlay).setBounds(bounds);
}//for//
Point result = new Point(maxX, y + maxHeight + marginBottom + marginHeight);
//Declarative Engineering: Layout any excluded controls that are visible - they will be expanded to fill the entire space.//
if(excluded != null) {
//Ensure there is enough space for any visible overlays.//
for(int index = 0; index < excluded.length; index++) {
if(excluded[index].getVisible()) {
RowData next = (RowData) excluded[index].getLayoutData();
int minWidth = next.minimumWidth;
int minHeight = next.minimumHeight;
boolean calcMinWidth = minWidth <= 0;
boolean calcMinHeight = minHeight <= 0;
//Calculate the minimum width and/or height if necessary.//
if(calcMinWidth || calcMinHeight) {
Point size = null;
if(excluded[index] instanceof Composite) {
excluded[index].computeSize(0, 0, true);
if(((Composite) excluded[index]).getLayout() instanceof Layout) {
size = ((Layout) ((Composite) excluded[index]).getLayout()).computeCurrentSize((Composite) excluded[index]);
}//if//
else { //Note This should never be run (all Brainstorm layouts should extend the Layout base class in Brainstorm). Also this fails to account for margins.//
Debug.log(new RuntimeException("Only Brainstorm based layouts may be used. The layout must extend " + Layout.class.getName()));
}//else//
}//if//
else {
size = excluded[index].computeSize(0, 0, true);
}//else//
if(calcMinWidth) {
minWidth = Math.max(0, size.x);
}//if//
if(calcMinHeight) {
minHeight = Math.max(0, size.y);
}//if//
}//if//
result.x = Math.max(result.x, minWidth);
result.y = Math.max(result.y, minHeight);
}//if//
}//for//
//Force all excluded widgets that are visible to fill the entire space (overlays).//
for(int index = 0; index < excluded.length; index++) {
if(excluded[index].getVisible()) {
int cx = x + marginWidth + marginLeft;
int cy = y + marginHeight + marginTop;
int cw = result.x - ((marginWidth << 1) + marginRight + marginLeft);
int ch = result.y - ((marginHeight << 1) + marginTop + marginBottom);
//Set the widget to fill the entire space.//
excluded[index].setBounds(cx, cy, cw, ch);
}//if//
}//for//
}//if//
return result;
}//layoutHorizontal()//
/**
* @param composite
* @param move
* @param wrap
* @param height
* @param flushCache
* @return
*/
Point layoutVertical(Composite composite, boolean move, boolean wrap, int height, boolean flushCache) {
Control[] children = composite.getChildren();
int count = 0; //The child count.//
Control[] excluded = null;
int nextExcludedIndex = 0;
IOverlay[] overlayChildren = new IOverlay[children.length];
int overlayCount = 0;
int childWidth = 0;
int childHeight = 0;
int maxWidth = 0;
int clientX = 0;
int clientY = 0;
int[] wraps = null;
boolean wrapped = false;
Rectangle[] rectangle = null;
int maxY = 0;
int x = marginLeft + marginWidth;
int y = marginTop + marginHeight;
int availableWidth = composite.getClientArea().width;
//Declarative Engineering//
//Moved above the following for loop in order to include invisible children (which may become visible later - we don't want the layout to change all the sizes of the components if they do become visible).//
//Modified to exclude the specifically excluded controls.//
for(int index = 0; index < children.length; index++) {
Control child = children[index];
RowData data = (RowData) child.getLayoutData();
//Ignore excluded and overlay controls.//
if(data == null || (!data.exclude && !(child instanceof IOverlay))) {
Point size = computeSize(child, flushCache);
childWidth = Math.max(childWidth, size.x);
childHeight = Math.max(childHeight, size.y);
}//if//
}//for//
maxWidth = childWidth;
//Modified to exclude invisible children and move overlays to another collection.//
for(int index = 0; index < children.length; index++) {
Control child = children[index];
RowData data = (RowData) child.getLayoutData();
if(child instanceof IOverlay) {
overlayChildren[overlayCount++] = (IOverlay) children[index];
}//if//
else if(data != null && data.exclude) {
if(excluded == null) {
int excludeCount = 1;
for(int i = index + 1; i < children.length; i++) {
RowData childData = (RowData) children[i].getLayoutData();
if(childData != null && childData.exclude) {
excludeCount++;
}//if//
}//for//
excluded = new Control[excludeCount];
}//if//
excluded[nextExcludedIndex++] = children[index];
}//else if//
else if(child.getVisible()) {
children[count++] = children[index];
}//else if//
}//for//
if(count == 0) {
return new Point(marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
}//if//
if(move) {
Rectangle rect = composite.getClientArea();
clientX = rect.x;
clientY = rect.y;
}//if//
if(move && justify) {
rectangle = new Rectangle[count];
wraps = new int[count];
}//if//
availableWidth = Math.max(maxWidth, availableWidth);
for(int i = 0; i < count; i++) {
Control child = children[i];
RowData data = (RowData) child.getLayoutData();
if(pack) {
Point size = computeSize(child, flushCache);
childWidth = size.x;
childHeight = size.y;
}//if//
if(wrap && (i != 0) && (y + childHeight > height)) {
wrapped = true;
if(move && justify) {
wraps[i - 1] = maxWidth;
}//if//
x += spacing + maxWidth;
y = marginTop + marginHeight;
if(pack) {
maxWidth = 0;
}//if//
}//if//
if(move) {
int childX = x + clientX;
int childY = y + clientY;
switch(data == null || data.alignment == SWT.NONE ? alignment : data.alignment) {
case SWT.FILL: {
childWidth = availableWidth - ((marginWidth << 1) + marginLeft + marginRight);
break;
}//case//
case SWT.END: {
childX += availableWidth - (childWidth + (marginWidth << 1) + marginLeft + marginRight);
break;
}//case//
case SWT.CENTER: {
childX += ((availableWidth - (childWidth + (marginWidth << 1) + marginLeft + marginRight)) >> 1);
break;
}//case//
}//switch//
if(justify) {
rectangle[i] = new Rectangle(childX, childY, childWidth, childHeight);
}//if//
else {
child.setBounds(childX, childY, childWidth, childHeight);
}//else//
}//if//
y += spacing + childHeight;
maxY = Math.max(maxY, y);
}//for//
maxY = Math.max(clientY + marginTop + marginHeight, maxY - spacing);
if(!wrapped) {
maxY += marginBottom + marginHeight;
}//if//
if(move && justify) {
int space = 0, margin = 0;
if(!wrapped) {
space = Math.max(0, (height - maxY) / (count + 1));
margin = Math.max(0, ((height - maxY) % (count + 1)) / 2);
}//if//
else {
int last = 0;
if(count > 0) {
wraps[count - 1] = maxWidth;
}//if//
for(int i = 0; i < count; i++) {
if(wraps[i] != 0) {
int wrapCount = i - last + 1;
int wrapY = 0;
for(int j = last; j <= i; j++) {
wrapY += rectangle[j].height + spacing;
}//for//
space = Math.max(0, (height - wrapY) / (wrapCount + 1));
margin = Math.max(0, ((height - wrapY) % (wrapCount + 1)) / 2);
for(int j = last; j <= i; j++) {
rectangle[j].y += (space * (j - last + 1)) + margin;
}//for//
last = i + 1;
}//if//
}//for//
}//else//
for(int i = 0; i < count; i++) {
if(!wrapped) {
rectangle[i].y += (space * (i + 1)) + margin;
}//if//
children[i].setBounds(rectangle[i]);
}//for//
}//if//
if(overlayCount > 0) { //Layout the overlays.//
int upperLeftOffset = 0;
int upperRightOffset = 0;
int lowerLeftOffset = 0;
int lowerRightOffset = 0;
Control lastPeer = null;
Arrays.sort(overlayChildren, 0, overlayCount, new Comparator() {
public int compare(Object arg0, Object arg1) {
return ((IOverlay) arg0).getPeerControl().hashCode() - ((IOverlay) arg1).getPeerControl().hashCode();
}//compare()//
});
for(int index = 0; index < overlayCount; index++) {
IOverlay overlay = overlayChildren[index];
Control peer = overlay.getPeerControl();
Rectangle bounds = peer.getBounds();
Point size = overlay.getSize();
if(peer != lastPeer) {
upperLeftOffset = 0;
upperRightOffset = 0;
lowerLeftOffset = 0;
lowerRightOffset = 0;
lastPeer = peer;
}//if//
switch(overlay.getPosition()) {
case IOverlay.POSITION_UPPER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + upperLeftOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperLeftOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_UPPER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - upperRightOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - lowerRightOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + lowerLeftOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerLeftOffset += bounds.width + 1;
break;
}//case//
}//switch//
((Control) overlay).setBounds(bounds);
}//for//
}//if//
Point result = new Point(x + maxWidth + marginRight + marginWidth, maxY);
//Declarative Engineering: Layout any excluded controls that are visible - they will be expanded to fill the entire space.//
if(excluded != null) {
//Ensure there is enough space for any visible overlays.//
for(int index = 0; index < excluded.length; index++) {
if(excluded[index].getVisible()) {
RowData next = (RowData) excluded[index].getLayoutData();
int minWidth = next.minimumWidth;
int minHeight = next.minimumHeight;
boolean calcMinWidth = minWidth <= 0;
boolean calcMinHeight = minHeight <= 0;
//Calculate the minimum width and/or height if necessary.//
if(calcMinWidth || calcMinHeight) {
Point size = null;
if(excluded[index] instanceof Composite) {
excluded[index].computeSize(0, 0, true);
if(((Composite) excluded[index]).getLayout() instanceof Layout) {
size = ((Layout) ((Composite) excluded[index]).getLayout()).computeCurrentSize((Composite) excluded[index]);
}//if//
else { //Note This should never be run (all Brainstorm layouts should extend the Layout base class in Brainstorm). Also this fails to account for margins.//
Debug.log(new RuntimeException("Only Brainstorm based layouts may be used. The layout must extend " + Layout.class.getName()));
}//else//
}//if//
else {
size = excluded[index].computeSize(0, 0, true);
}//else//
if(calcMinWidth) {
minWidth = Math.max(0, size.x);
}//if//
if(calcMinHeight) {
minHeight = Math.max(0, size.y);
}//if//
}//if//
result.x = Math.max(result.x, minWidth);
result.y = Math.max(result.y, minHeight);
}//if//
}//for//
//Force all excluded widgets that are visible to fill the entire space (overlays).//
for(int index = 0; index < excluded.length; index++) {
if(excluded[index].getVisible()) {
int cx = x + marginWidth + marginLeft;
int cy = y + marginHeight + marginTop;
int cw = result.x - ((marginWidth << 1) + marginRight + marginLeft);
int ch = result.y - ((marginHeight << 1) + marginTop + marginBottom);
//Set the widget to fill the entire space.//
excluded[index].setBounds(cx, cy, cw, ch);
}//if//
}//for//
}//if//
return result;
}//layoutVertical()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
String string = "RowLayout {";
string += "type=" + ((type != SWT.HORIZONTAL) ? "SWT.VERTICAL" : "SWT.HORIZONTAL") + " ";
if(marginWidth != 0)
string += "marginWidth=" + marginWidth + " ";
if(marginHeight != 0)
string += "marginHeight=" + marginHeight + " ";
if(marginLeft != 0)
string += "marginLeft=" + marginLeft + " ";
if(marginTop != 0)
string += "marginTop=" + marginTop + " ";
if(marginRight != 0)
string += "marginRight=" + marginRight + " ";
if(marginBottom != 0)
string += "marginBottom=" + marginBottom + " ";
if(spacing != 0)
string += "spacing=" + spacing + " ";
string += "wrap=" + wrap + " ";
string += "pack=" + pack + " ";
string += "alignment=" + alignment + " ";
string += "justify=" + justify + " ";
string = string.trim();
string += "}";
return string;
}//toString()//
}//RowLayout//

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2003,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/*
* This layout is designed only for use in the wizard control. The layout will size the container to the largest control, and will resize visible controls to the container size.
*/
public class WizardLayout extends Layout {
/**
* WizardLayout constructor.
*/
public WizardLayout() {
}//WizardLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeMinSize(org.eclipse.swt.graphics.Point, org.eclipse.swt.widgets.Composite, boolean)
*/
public void computeMinSize(Point result, Composite composite, boolean flushCache) {
//TODO:
}//computeMinSize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#flushCache(org.eclipse.swt.widgets.Control)
*/
public boolean flushCache(Control child) {
//TODO:
return false;
}//flushCache()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
Control[] children = composite.getChildren();
int count = children.length;
int maxWidth = 0, maxHeight = 0;
//Determine the maximum size of the container.//
//TODO: Should we only use the size of the currently visible control?//
for(int index = 0; index < count; index++) {
Control child = children[index];
Point point = child.computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
maxWidth = Math.max(maxWidth, point.x);
maxHeight = Math.max(maxHeight, point.y);
}//for//
return new Point(maxWidth, maxHeight);
}//computeSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Control[] children = composite.getChildren();
Rectangle clientArea = composite.getClientArea();
Control child = null;
for(int index = 0; ((child == null) && (index < children.length)); index++) {
//if(children[index].isVisible()) {
// child = children[index];
//}//if//
children[index].setBounds(clientArea);
}//for//
if(child != null) {
// child.setBounds(clientArea);
//child.moveAbove()
}//if//
}//layout()//
}//WizardLayout//