/******************************************************************************* * 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; } }