// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.dataprofiler.core.ui.grid;
import org.eclipse.nebula.widgets.grid.GridColumn;
import org.eclipse.nebula.widgets.grid.ITalendGridHeaderRendererHandler;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.TextLayout;
import org.eclipse.swt.graphics.Transform;
import org.eclipse.swt.widgets.Display;
/**
* The column header renderer.
*/
public class TdColumnHeaderRenderer extends AbstractColumnHerderRenderer implements ITalendGridHeaderRendererHandler {
int leftMargin = 6;
int rightMargin = 6;
int topMargin = 3;
int bottomMargin = 3;
int imageSpacing;
private TextLayout textLayout;
/** rotation of the header text. */
protected int _rotation;
/** Transformations for rotated text. */
protected Transform _transform;
/** inverse transformation to reset gc. */
protected Transform _transformInv;
private double sinRotation;
private double cosRotation;
public TdColumnHeaderRenderer() {
_transform = new Transform(Display.getCurrent());
_transformInv = new Transform(Display.getCurrent());
_transform.rotate(-_rotation);
_transformInv.rotate(-_rotation);
_transformInv.invert();
sinRotation = Math.sin(_rotation * Math.PI / 180);
cosRotation = Math.cos(_rotation * Math.PI / 180);
imageSpacing = (int) (10 / sinRotation);
}
/**
* {@inheritDoc}
*/
public Point computeSize(GC gc, int wHint, int hHint, Object value) {
GridColumn column = (GridColumn) value;
gc.setFont(column.getHeaderFont());
int x = leftMargin;
int y = topMargin + gc.getFontMetrics().getHeight() + bottomMargin;
if (column.getImage() != null) {
x += column.getImage().getBounds().width + imageSpacing;
y = Math.max(y, topMargin + column.getImage().getBounds().height + bottomMargin);
}
if (!isWordWrap()) {
x += gc.stringExtent(column.getText()).x + rightMargin;
y += gc.stringExtent(column.getText()).x * sinRotation;
} else {
int plainTextWidth;
if (wHint == SWT.DEFAULT) {
plainTextWidth = getBounds().width - x - rightMargin;
} else {
plainTextWidth = wHint - x - rightMargin;
}
getTextLayout(gc, column);
textLayout.setText(column.getText());
textLayout.setWidth(plainTextWidth < 1 ? 1 : plainTextWidth);
x += plainTextWidth + rightMargin;
int textHeight = topMargin;
textHeight += textLayout.getBounds().height;
textHeight += bottomMargin;
y = Math.max(y, textHeight);
}
y += computeControlSize(column).y;
return new Point(x, y);
}
/**
* {@inheritDoc}
*/
public void paint(GC gc, Object value) {
gc.setAntialias(SWT.ON);
gc.setTransform(_transform);
float[] original = { (float) getBounds().x - 2, (float) getBounds().y + (float) getBounds().height - 2 };
_transformInv.transform(original);
GridColumn column = (GridColumn) value;
// set the font to be used to display the text.
gc.setFont(column.getHeaderFont());
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
if (isSelected()) {
gc.setBackground(IndicatorSelectGrid.highlightBlue);
gc.fillRectangle((int) original[0], (int) original[1] + 2, (int) (getBounds().height / sinRotation)
+ getBounds().width, (int) (getBounds().width * sinRotation));
}
int x = leftMargin;
int width = getBounds().width - x;
width -= rightMargin;
float[] cords = { (getBounds().x + width / 2 - leftMargin), (getBounds().y + (float) getBounds().height - topMargin) };
_transformInv.transform(cords);
if (column.getImage() != null) {
gc.drawImage(column.getImage(), (int) cords[0] + leftMargin + imageSpacing, (int) cords[1]);
x += column.getImage().getBounds().width;
}
gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND));
String text = column.getText();
if (column.getAlignment() == SWT.RIGHT) {
int len = gc.stringExtent(text).x;
if (len < width) {
x += width - len;
}
} else if (column.getAlignment() == SWT.CENTER) {
int len = gc.stringExtent(text).x;
if (len < width) {
x += (width - len) / 2;
}
}
gc.drawString(text, (int) cords[0] + x + imageSpacing, (int) cords[1] + topMargin);
gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
gc.drawLine((int) (original[0]), (int) (original[1]),
(int) (original[0] + getBounds().height / sinRotation - imageSpacing), (int) (original[1]));
gc.drawLine((int) (original[0]), (int) (original[1] + getBounds().width * sinRotation), (int) (original[0]
+ getBounds().height / sinRotation + getBounds().width * cosRotation - imageSpacing - leftMargin),
(int) (original[1] + getBounds().width * sinRotation));
gc.setTransform(null);
gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND));
gc.drawLine(getBounds().x, getBounds().y + getBounds().height - 1, getBounds().x + getBounds().width, getBounds().y
+ getBounds().height - 1);
}
/**
* {@inheritDoc}
*/
public boolean notify(int event, Point point, Object value) {
return false;
}
/**
* @return the bounds reserved for the control
*/
@Override
protected Rectangle getControlBounds(Object value, boolean preferred) {
Rectangle bounds = getBounds();
GridColumn column = (GridColumn) value;
Point controlSize = computeControlSize(column);
int y = getBounds().y + getBounds().height - bottomMargin - controlSize.y;
return new Rectangle(bounds.x + 3, y, bounds.width - 6, controlSize.y);
}
private Point computeControlSize(GridColumn column) {
if (column.getHeaderControl() != null) {
return column.getHeaderControl().computeSize(SWT.DEFAULT, SWT.DEFAULT);
}
return new Point(0, 0);
}
private void getTextLayout(GC gc, GridColumn column) {
if (textLayout == null) {
textLayout = new TextLayout(gc.getDevice());
textLayout.setFont(gc.getFont());
column.getParent().addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
textLayout.dispose();
}
});
}
textLayout.setAlignment(column.getAlignment());
}
/**
* Set the rotation of the header text. Please note that you have to call <code>redraw()</code> on the table
* yourself if you change the rotation while the table is showing.
*
* @param rotation rotation in degrees anti clockwise between 0 and 90 degrees.
*/
public void setRotation(int rotation) {
if (rotation < 0 || rotation > 90) {
throw new IllegalArgumentException("Rotation range 0..90");
}
if (_rotation != rotation) {
disposeTransformations();
_rotation = rotation;
_transform = new Transform(Display.getCurrent());
_transformInv = new Transform(Display.getCurrent());
_transform.rotate(-rotation);
_transformInv.rotate(-rotation);
_transformInv.invert();
sinRotation = Math.sin(_rotation * Math.PI / 180);
imageSpacing = (int) (10 / sinRotation);
}
}
/**
* Getter for rotation.
*
* @return the rotation
*/
public int getRotation() {
return _rotation;
}
private void disposeTransformations() {
if (_transform != null) {
_transform.dispose();
}
if (_transformInv != null) {
_transformInv.dispose();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.nebula.widgets.grid.ITalendGridHeaderRendererHandle#dispose()
*/
public void dispose() {
disposeTransformations();
}
}