blob: 625b33e42ee0e61254bd7f9d6bf26886f83962a4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Luis Carlos Moreira da Costa.
* 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:
* Luis Carlos Moreira da Costa (tcljava at gmail dot com) - initial API and implementation
*******************************************************************************/
package org.mihalis.opal.dynamictablecolumns;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
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.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TreeColumn;
/**
*
* DynamicTableColumnLayout
*
* <p>Manages the length of a set of columns.</p>
*
*/
public class DynamicTableColumnLayout extends Layout {
/** The mcolumns. */
private final List<DynamicColumnData> mcolumns = new LinkedList<DynamicColumnData>();
/** The pcolumns. */
private final List<DynamicColumnData> pcolumns = new LinkedList<DynamicColumnData>();
/** The map column data. */
private final Map<TableColumn, DynamicColumnData> mapColumnData = new HashMap<TableColumn, DynamicColumnData>();
/** The installed listeners. */
private final Map<Composite, Listener> installedListeners = new HashMap<Composite, Listener>();
/** The total fixed width. */
private int totalFixedWidth = 0;
/** The total perct width. */
private double totalPerctWidth = 0.0d;
/**
* Set dynamic column data.
*
* @param dynamicColumnData DynamicColumnData
*/
public void setColumnData(final DynamicColumnData dynamicColumnData) {
this.mapColumnData.put(dynamicColumnData.getTableColumn(), dynamicColumnData);
this.mcolumns.add(dynamicColumnData);
if (dynamicColumnData.getPreferredLength().getMeasure() == DynamicLengthMeasure.PERCENTAGE) {
this.pcolumns.add(dynamicColumnData);
}
}
/**
* Set column data.
*
* @param tableColumn TableColumn
* @param preferredLength String
* @param minLength String
*/
public void setColumnData(final TableColumn tableColumn, final String preferredLength, final String minLength) {
setColumnData(new DynamicColumnData(tableColumn, preferredLength, minLength));
}
/**
* Set column data.
*
* @param tableColumn TableColumn
* @param preferredLength String
*/
public void setColumnData(final TableColumn tableColumn, final String preferredLength) {
setColumnData(new DynamicColumnData(tableColumn, preferredLength));
}
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
@Override
protected Point computeSize(final Composite composite, final int wHint, final int hHint, final boolean flushCache) {
if (this.installedListeners.get(composite) == null) {
final Listener listener = new Listener() {
@Override
public void handleEvent(final Event event) {
composite.layout();
}
};
composite.addListener(SWT.Resize, listener);
this.installedListeners.put(composite, listener);
}
final Control child = composite.getChildren()[0];
final Point childSize = child.computeSize(wHint, hHint);
int width = Math.max(0, childSize.x);
int height = Math.max(0, childSize.y);
if (wHint != SWT.DEFAULT) {
width = wHint;
}
if (hHint != SWT.DEFAULT) {
height = hHint;
}
return new Point(width, height);
}
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
@Override
protected void layout(final Composite composite, final boolean flushCache) {
final Rectangle containerArea = composite.getClientArea();
final Scrollable table = getControl(composite);
table.setBounds(containerArea);
final Rectangle tableArea = table.getClientArea();
this.totalFixedWidth = 0;
this.totalPerctWidth = 0;
// Calculate totals
for (final DynamicColumnData column : this.mcolumns) {
if (column.isVisible()) {
final DynamicLength prefLength = column.getPreferredLength();
final DynamicLength minLength = column.getMinLength();
if (prefLength.getValue() != 0) {
addTotalLength(prefLength);
} else {
addTotalLength(minLength);
}
}
}
final Integer precentPixelWidth = (tableArea.width - this.totalFixedWidth);
// Set widths
for (final DynamicColumnData dynamicColumnData : this.mcolumns) {
if (dynamicColumnData.isVisible()) {
final DynamicLength prefLength = dynamicColumnData.getPreferredLength();
final Double prefLengthValue = prefLength.getValue();
final DynamicLengthMeasure prefLengthMeasure = prefLength.getMeasure();
final DynamicLength minLength = dynamicColumnData.getMinLength();
final Double minLengthValue = minLength.getValue();
switch (prefLengthMeasure) {
case PIXEL:
updateColumnWidth(dynamicColumnData, Math.max(prefLengthValue, minLengthValue));
break;
case PERCENTAGE:
final double percentFromTotal = (prefLengthValue / this.totalPerctWidth);
final int width = (int) (percentFromTotal * precentPixelWidth);
updateColumnWidth(dynamicColumnData, Math.max(width, minLengthValue));
}
} else {
updateColumnWidth(dynamicColumnData, 0d);
}
}
}
/**
* Add total length.
*
* @param dynamicLength DynamicLength
* @return boolean
*/
private boolean addTotalLength(final DynamicLength dynamicLength) {
switch (dynamicLength.getMeasure()) {
case PIXEL:
this.totalFixedWidth += dynamicLength.getValue();
break;
case PERCENTAGE:
this.totalPerctWidth += dynamicLength.getValue();
}
return (dynamicLength.getValue() != 0);
}
/**
* Redistribute percentage.
*
* @param tableColumn TableColumn
* @param value Double
*/
public void redistributePercentage(final TableColumn tableColumn, final Double value) {
final int qtdCols = (this.pcolumns.size() - 1);
for (final DynamicColumnData data : this.pcolumns) {
final DynamicLength preferredLength = data.getPreferredLength();
if (tableColumn != data.getTableColumn()) {
preferredLength.setValue((preferredLength.getValue() + (value / qtdCols)));
}
}
}
/**
* Update column width.
*
* @param dynamicColumnData DynamicColumnData
* @param width Double
*/
private void updateColumnWidth(final DynamicColumnData dynamicColumnData, final Double width) {
final TableColumn tableColumn = dynamicColumnData.getTableColumn();
final TreeColumn treeColumn = dynamicColumnData.getTreeColumn();
if (tableColumn != null) {
tableColumn.setWidth(width.intValue());
} else if (treeColumn != null) {
treeColumn.setWidth(width.intValue());
} else {
throw new IllegalStateException("No valid to set the column width!");
}
}
/**
* Get column data.
*
* @param tableColumn TableColumn
* @return DynamicColumnData
*/
public DynamicColumnData getColumnData(final TableColumn tableColumn) {
return this.mapColumnData.get(tableColumn);
}
/**
* Get control.
*
* @param composite Composite
* @return Scrollable
*/
Scrollable getControl(final Composite composite) {
return ((Scrollable) composite.getChildren()[0]);
}
}