blob: 528480cf54e37e6e186329319862421181ccf295 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.e4.ui.workbench.renderers.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Layout;
/**
* This arranges its controls into 5 'slots' defined by its composite children
* <ol>
* <li>Top: spans the entire width and abuts the top of the container</li>
* <li>Bottom: spans the entire width and abuts the bottom of the container</li>
* <li>Left: spans the space between 'top' and 'bottom' and abuts the left of
* the container</li>
* <li>Right: spans the space between 'top' and 'bottom' and abuts the right of
* the container</li>
* <li>Center: fills the area remaining once the other controls have been
* positioned</li>
* </ol>
*
* <strong>NOTE:</strong> <i>All</i> the child controls must exist. Also,
* computeSize is not implemented because we expect this to be used in
* situations (i.e. shells) where the outer bounds are always 'set', not
* computed. Also, the interior structure of the center may contain overlapping
* controls so it may not be capable of performing the calculation.
*
* @author emoffatt
*
*/
public class TrimmedPartLayout extends Layout {
/**
* gutterBottom specifies the number of pixels of vertical margin that will
* be placed between the bottom trim component and the bottom edge of the
* client area. If there is no bottom trim component, the gutter serves as a
* margin.
*
* The default value is 0.
*/
public int gutterBottom = 0;
/**
* gutterLeft specifies the number of pixels of horizontal margin that will
* be placed between the left trim component and the left edge of the client
* area. If there is no left trim component, the gutter serves as a margin.
*
* The default value is 0.
*/
public int gutterLeft = 0;
/**
* gutterTop specifies the number of pixels of vertical margin that will be
* placed between the top trim component and the top edge of the client
* area. If there is no top trim component, the gutter serves as a margin.
*
* The default value is 0.
*/
public int gutterTop = 0;
/**
* gutterRight specifies the number of pixels of horizontal margin that will
* be placed between the right trim component and the right edge of the
* client area. If there is no right trim component, the gutter serves as a
* margin.
*
* The default value is 0.
*/
public int gutterRight = 0;
public Composite top;
public Composite bottom;
public Composite left;
public Composite right;
public Composite clientArea;
/**
* This layout is used to support parts that want trim for their containing
* composites.
*
* @param trimOwner
*/
public TrimmedPartLayout(Composite parent) {
clientArea = new Composite(parent, SWT.NONE);
clientArea.setLayout(new FillLayout());
}
@Override
protected Point computeSize(Composite composite, int wHint, int hHint,
boolean flushCache) {
// We can't actually compute a size so return a default
return new Point(SWT.DEFAULT, SWT.DEFAULT);
}
@Override
protected void layout(Composite composite, boolean flushCache) {
Rectangle ca = composite.getClientArea();
Rectangle caRect = new Rectangle(ca.x, ca.y, ca.width, ca.height);
// 'Top' spans the entire area
if (top != null && top.isVisible()) {
Point topSize = top.computeSize(caRect.width, SWT.DEFAULT, true);
caRect.y += topSize.y;
caRect.height -= topSize.y;
// Don't layout unless we've changed
Rectangle newBounds = new Rectangle(ca.x, ca.y, caRect.width,
topSize.y);
if (!newBounds.equals(top.getBounds())) {
top.setBounds(newBounds);
}
}
// Include the gutter whether there is a top area or not.
caRect.y += gutterTop;
caRect.height -= gutterTop;
// 'Bottom' spans the entire area
if (bottom != null && bottom.isVisible()) {
Point bottomSize = bottom.computeSize(caRect.width, SWT.DEFAULT,
true);
caRect.height -= bottomSize.y;
// Don't layout unless we've changed
Rectangle newBounds = new Rectangle(caRect.x, caRect.y
+ caRect.height, caRect.width, bottomSize.y);
if (!newBounds.equals(bottom.getBounds())) {
bottom.setBounds(newBounds);
}
}
caRect.height -= gutterBottom;
// 'Left' spans between 'top' and 'bottom'
if (left != null && left.isVisible()) {
Point leftSize = left.computeSize(SWT.DEFAULT, caRect.height, true);
caRect.x += leftSize.x;
caRect.width -= leftSize.x;
// Don't layout unless we've changed
Rectangle newBounds = new Rectangle(caRect.x - leftSize.x,
caRect.y, leftSize.x, caRect.height);
if (!newBounds.equals(left.getBounds())) {
left.setBounds(newBounds);
}
}
caRect.x += gutterLeft;
caRect.width -= gutterLeft;
// 'Right' spans between 'top' and 'bottom'
if (right != null && right.isVisible()) {
Point rightSize = right.computeSize(SWT.DEFAULT, caRect.height,
true);
caRect.width -= rightSize.x;
// Don't layout unless we've changed
Rectangle newBounds = new Rectangle(caRect.x + caRect.width,
caRect.y, rightSize.x, caRect.height);
if (!newBounds.equals(right.getBounds())) {
right.setBounds(newBounds);
}
}
caRect.width -= gutterRight;
// Don't layout unless we've changed
if (!caRect.equals(clientArea.getBounds())) {
clientArea.setBounds(caRect);
}
}
/**
* @param top2
* @param b
* @return
*/
public Composite getTrimComposite(Composite parent, int side) {
if (side == SWT.TOP) {
if (top == null) {
top = new Composite(parent, SWT.NONE);
top.setLayout(new TrimBarLayout(true));
top.addDisposeListener(e -> top = null);
}
return top;
} else if (side == SWT.BOTTOM) {
if (bottom == null) {
bottom = new Composite(parent, SWT.NONE);
bottom.setLayout(new TrimBarLayout(true));
bottom.addDisposeListener(e -> bottom = null);
}
return bottom;
} else if (side == SWT.LEFT) {
if (left == null) {
left = new Composite(parent, SWT.NONE);
left.setLayout(new TrimBarLayout(false));
left.addDisposeListener(e -> left = null);
}
return left;
} else if (side == SWT.RIGHT) {
if (right == null) {
right = new Composite(parent, SWT.NONE);
right.setLayout(new TrimBarLayout(false));
right.addDisposeListener(e -> right = null);
}
return right;
}
// Unknown location
return null;
}
public Rectangle getTrimRect(int side) {
Rectangle caBounds = clientArea.getBounds();
caBounds = Display.getCurrent().map(clientArea.getParent(), null,
caBounds);
if (side == SWT.TOP) {
if (top != null) {
Rectangle b = top.getBounds();
b = top.getDisplay().map(top.getParent(), null, b);
return b;
}
// Fake one
caBounds.height = 25;
return caBounds;
}
if (side == SWT.BOTTOM) {
if (bottom != null) {
Rectangle b = bottom.getBounds();
b = bottom.getDisplay().map(bottom.getParent(), null, b);
return b;
}
// Fake one
caBounds.y = (caBounds.y + caBounds.height) - 25;
caBounds.height = 25;
return caBounds;
}
if (side == SWT.LEFT) {
if (left != null && left.getChildren().length > 0) {
Rectangle b = left.getBounds();
b = left.getDisplay().map(left.getParent(), null, b);
return b;
}
// Fake one
caBounds.width = 25;
return caBounds;
}
if (side == SWT.RIGHT) {
if (right != null && right.getChildren().length > 0) {
Rectangle b = right.getBounds();
b = right.getDisplay().map(right.getParent(), null, b);
return b;
}
// Fake one
caBounds.x = (caBounds.x + caBounds.width) - 25;
caBounds.width = 25;
return caBounds;
}
return null;
}
}