org.eclipse.jface.layout.AbstractColumnLayout Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.jface Show documentation
Show all versions of org.eclipse.jface Show documentation
This is org.eclipse.jface jar used by Scout SDK
The newest version!
/*******************************************************************************
* Copyright (c) 2006, 2015 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 (original file org.eclipse.ui.texteditor.templates.ColumnLayout)
* Tom Schindl - refactored to be widget independent (bug 171824)
* - fix for bug 178280, 184342, 184045, 208014, 214532
* Micah Hainline - fix in bug: 208335
*******************************************************************************/
package org.eclipse.jface.layout;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.util.Policy;
import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.ColumnLayoutData;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Widget;
/**
* The AbstractColumnLayout is a {@link Layout} used to set the size of a table
* in a consistent way even during a resize unlike a {@link TableLayout} which
* only sets initial sizes.
*
*
* You can only add the layout to a container whose only child is the
* table/tree control you want the layouts applied to.
*
*
* @since 3.4
*/
public abstract class AbstractColumnLayout extends Layout {
private static int COLUMN_TRIM;
static {
if (Util.isWindows()) {
COLUMN_TRIM = 4;
} else if (Util.isMac()) {
COLUMN_TRIM = 24;
} else {
COLUMN_TRIM = 3;
}
}
static final boolean IS_GTK = Util.isGtk();
/**
* Key used to restore the layout data in the columns data-slot
* @since 3.5
*/
protected static final String LAYOUT_DATA = Policy.JFACE + ".LAYOUT_DATA"; //$NON-NLS-1$
private boolean inupdateMode = false;
private boolean relayout = true;
private boolean adjustForScrollBar = false;
private Listener resizeListener = event -> {
if (!inupdateMode) {
updateColumnData(event.widget);
}
};
/**
* Creates a new abstract column layout.
*/
public AbstractColumnLayout() {
}
/**
* Creates a new abstract column layout.
*
* @param adjustForScrollBar
* true
if the layout should reserve space for the
* vertical scroll bar
* @since 3.12
*/
public AbstractColumnLayout(boolean adjustForScrollBar) {
this.adjustForScrollBar = adjustForScrollBar;
}
/**
* Adds a new column of data to this table layout.
*
* @param column
* the column
*
* @param data
* the column layout data
*/
public void setColumnData(Widget column, ColumnLayoutData data) {
if (column.getData(LAYOUT_DATA) == null) {
column.addListener(SWT.Resize, resizeListener);
}
column.setData(LAYOUT_DATA, data);
}
/**
* Compute the size of the table or tree based on the ColumnLayoutData and
* the width and height hint.
*
* @param scrollable
* the widget to compute
* @param wHint
* the width hint
* @param hHint
* the height hint
* @return Point where x is the width and y is the height
*/
private Point computeTableTreeSize(Scrollable scrollable, int wHint,
int hHint) {
Point result = scrollable.computeSize(wHint, hHint);
int width = scrollable.getBorderWidth() * 2;
if (adjustForScrollBar && scrollable.getVerticalBar() != null) {
width += scrollable.getVerticalBar().getSize().x;
}
int size = getColumnCount(scrollable);
for (int i = 0; i < size; ++i) {
ColumnLayoutData layoutData = getLayoutData(scrollable, i);
if (layoutData instanceof ColumnPixelData) {
ColumnPixelData col = (ColumnPixelData) layoutData;
width += col.width;
if (col.addTrim) {
width += getColumnTrim();
}
} else if (layoutData instanceof ColumnWeightData) {
ColumnWeightData col = (ColumnWeightData) layoutData;
width += col.minimumWidth;
} else {
Assert.isTrue(false, "Unknown column layout data"); //$NON-NLS-1$
}
}
result.x = width;
return result;
}
/**
* Layout the scrollable based on the supplied width and area. Only increase
* the size of the scrollable if increase is true
.
*
* @param scrollable
* @param width
* @param area
* @param increase
*/
private void layoutTableTree(final Scrollable scrollable, final int width,
final Rectangle area, final boolean increase) {
final int numberOfColumns = getColumnCount(scrollable);
final int[] widths = new int[numberOfColumns];
final int[] weightColumnIndices = new int[numberOfColumns];
int numberOfWeightColumns = 0;
int fixedWidth = 0;
int totalWeight = 0;
// First calc space occupied by fixed columns
for (int i = 0; i < numberOfColumns; i++) {
ColumnLayoutData col = getLayoutData(scrollable, i);
if (col instanceof ColumnPixelData) {
ColumnPixelData cpd = (ColumnPixelData) col;
int pixels = cpd.width;
if (cpd.addTrim) {
pixels += getColumnTrim();
}
widths[i] = pixels;
fixedWidth += pixels;
} else if (col instanceof ColumnWeightData) {
ColumnWeightData cw = (ColumnWeightData) col;
weightColumnIndices[numberOfWeightColumns] = i;
numberOfWeightColumns++;
totalWeight += cw.weight;
} else {
Assert.isTrue(false, "Unknown column layout data"); //$NON-NLS-1$
}
}
if (adjustForScrollBar) {
ScrollBar verticalBar = scrollable.getVerticalBar();
if (verticalBar != null && scrollable.getScrollbarsMode() == SWT.NONE && !verticalBar.isVisible()) {
fixedWidth += verticalBar.getSize().x;
}
}
boolean recalculate;
do {
recalculate = false;
for (int i = 0; i < numberOfWeightColumns; i++) {
int colIndex = weightColumnIndices[i];
ColumnWeightData cw = (ColumnWeightData) getLayoutData(
scrollable, colIndex);
final int minWidth = cw.minimumWidth;
final int allowedWidth = totalWeight == 0 ? 0
: (width - fixedWidth) * cw.weight / totalWeight;
if (allowedWidth < minWidth) {
/*
* if the width assigned by weight is less than the minimum,
* then treat this column as fixed, remove it from weight
* calculations, and recalculate other weights.
*/
numberOfWeightColumns--;
totalWeight -= cw.weight;
fixedWidth += minWidth;
widths[colIndex] = minWidth;
System.arraycopy(weightColumnIndices, i + 1,
weightColumnIndices, i, numberOfWeightColumns - i);
recalculate = true;
break;
}
widths[colIndex] = allowedWidth;
}
} while (recalculate);
if (increase) {
scrollable.setSize(area.width, area.height);
}
inupdateMode = true;
setColumnWidths(scrollable, widths);
scrollable.update();
inupdateMode = false;
if (!increase) {
scrollable.setSize(area.width, area.height);
}
}
@Override
protected Point computeSize(Composite composite, int wHint, int hHint,
boolean flushCache) {
return computeTableTreeSize(getControl(composite), wHint, hHint);
}
@Override
protected void layout(Composite composite, boolean flushCache) {
Rectangle area = composite.getClientArea();
Scrollable table = getControl(composite);
int tableWidth = table.getSize().x;
int trim = computeTrim(area, table, tableWidth);
int width = Math.max(0, area.width - trim);
if (width > 1)
layoutTableTree(table, width, area, tableWidth < area.width);
// For the first time we need to relayout because Scrollbars are not
// calculate appropriately
if (relayout) {
relayout = false;
composite.layout();
}
}
/**
* Compute the area required for trim.
*
* @param area
* @param scrollable
* @param currentWidth
* @return int
*/
private int computeTrim(Rectangle area, Scrollable scrollable,
int currentWidth) {
int trim;
if (currentWidth > 1) {
trim = currentWidth - scrollable.getClientArea().width;
} else {
// initially, the table has no extend and no client area - use the
// border with
// plus some padding as educated guess
trim = 2 * scrollable.getBorderWidth() + 1;
}
return trim;
}
/**
* Get the control being laid out.
*
* @param composite
* the composite with the layout
* @return {@link Scrollable}
*/
Scrollable getControl(Composite composite) {
return (Scrollable) composite.getChildren()[0];
}
/**
* Get the number of columns for the receiver.
*
* @param tableTree
* the control
*
* @return the number of columns
* @since 3.5
*/
protected abstract int getColumnCount(Scrollable tableTree);
/**
* Set the widths of the columns.
*
* @param tableTree
* the control
*
* @param widths
* the widths of the column
* @since 3.5
*/
protected abstract void setColumnWidths(Scrollable tableTree, int[] widths);
/**
* Get the layout data for a column
*
* @param tableTree
* the control
* @param columnIndex
* the column index
* @return the layout data, might not null
* @since 3.5
*/
protected abstract ColumnLayoutData getLayoutData(Scrollable tableTree,
int columnIndex);
/**
* Update the layout data for a column
*
* @param column
* the column
* @since 3.5
*/
protected abstract void updateColumnData(Widget column);
/**
* The number of extra pixels taken as horizontal trim by the table column.
* To ensure there are N pixels available for the content of the column,
* assign N+COLUMN_TRIM for the column width.
*
* @return the trim used by the columns
* @since 3.4
*/
protected int getColumnTrim() {
return COLUMN_TRIM;
}
}