package name.abuchen.portfolio.ui.util.viewers;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.OwnerDrawLabelProvider;
import org.eclipse.jface.viewers.ViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.TextLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import name.abuchen.portfolio.money.Values;
public abstract class SharesLabelProvider extends OwnerDrawLabelProvider
{
private static final char POINT = new DecimalFormatSymbols().getDecimalSeparator();
private final NumberFormat format = new DecimalFormat("#,##0.###"); //$NON-NLS-1$
private ColumnViewer viewer;
private TextLayout cachedTextLayout;
public Color getForeground(Object element)
{
return null;
}
public Color getBackground(Object element)
{
return null;
}
public abstract Long getValue(Object element);
@Override
public String getToolTipText(Object element)
{
Long value = getValue(element);
return value != null ? Values.Share.format(value) : null;
}
private TextLayout getSharedTextLayout(Display display)
{
if (this.cachedTextLayout == null)
{
int orientation = this.viewer.getControl().getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
this.cachedTextLayout = new TextLayout(display);
this.cachedTextLayout.setOrientation(orientation);
}
return this.cachedTextLayout;
}
@Override
protected void initialize(ColumnViewer viewer, ViewerColumn column)
{
this.viewer = viewer;
super.initialize(viewer, column);
}
private Rectangle getSize(Event event, String text)
{
String s = text;
int p = s.indexOf(POINT);
if (p >= 0)
s = s.substring(0, p);
TextLayout textLayout = getSharedTextLayout(event.display);
textLayout.setText(s + ",000"); //$NON-NLS-1$
return textLayout.getBounds();
}
private Rectangle getBounds(Widget widget, int index)
{
if (widget instanceof TableItem)
return ((TableItem) widget).getBounds(index);
else if (widget instanceof TreeItem)
return ((TreeItem) widget).getBounds(index);
else
throw new IllegalArgumentException();
}
@Override
protected void measure(Event event, Object element)
{
Long value = getValue(element);
if (value != null)
{
String text = format.format(value / Values.Share.divider());
Rectangle size = getSize(event, text);
Rectangle tableItem = getBounds(event.item, event.index);
int width = Math.min(size.width, tableItem.width);
event.setBounds(new Rectangle(event.x + tableItem.width - width, event.y, //
width, event.height));
}
}
@Override
protected void paint(Event event, Object element)
{
Rectangle tableItem = getBounds(event.item, event.index);
boolean isSelected = (event.detail & SWT.SELECTED) != 0 || (event.detail & SWT.HOT) != 0;
if (!isSelected)
fillBackground(event, element, tableItem);
Long value = getValue(element);
if (value == null)
return;
Color oldForeground = null;
Color newForeground = isSelected ? null : getForeground(element);
if (newForeground != null)
{
oldForeground = event.gc.getForeground();
event.gc.setForeground(newForeground);
}
String text = format.format(value / Values.Share.divider());
Rectangle size = getSize(event, text);
TextLayout textLayout = getSharedTextLayout(event.display);
textLayout.setText(text);
Rectangle layoutBounds = textLayout.getBounds();
int x = event.x + tableItem.width - Math.min(size.width, tableItem.width);
int y = tableItem.y + Math.max(0, (tableItem.height - layoutBounds.height) / 2);
textLayout.draw(event.gc, x, y);
if (oldForeground != null)
event.gc.setForeground(oldForeground);
}
private void fillBackground(Event event, Object element, Rectangle bounds)
{
Color newBackground = getBackground(element);
if (newBackground != null)
{
Color oldBackground = event.gc.getBackground();
event.gc.setBackground(newBackground);
event.gc.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height);
event.gc.setBackground(oldBackground);
}
}
@Override
protected void erase(Event event, Object element)
{
// use os-specific background
}
}