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