package com.peterhi.ui.tempbars;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.peterhi.ui.UIImageResource;
public final class StripBar extends Canvas implements Listener {
private final List<StripItemController> itemControllers = new ArrayList<StripItemController>();
static final int barMarginLeft = 5;
static final int barMarginRight = 5;
static final int barMarginTop = 5;
static final int barMarginBottom = 5;
static final int itemSpacing = 5;
static final int itemMarginLeft = 8;
static final int itemMarginRight = 8;
static final int itemMarginTop = 5;
static final int itemMarginBottom = 5;
static final int itemTextExtraSpaceBefore = 5;
static final int itemCloseButtonExtraSpaceBefore = 10;
static final int itemArcSize = 6;
public StripBar(Composite parent, int style) {
super(parent, style);
addListener(SWT.SetData, this);
addListener(SWT.Paint, this);
addListener(SWT.Dispose, this);
}
@Override
public void handleEvent(Event event) {
if (equals(event.widget)) {
if (event.type == SWT.SetData) {
onSetData(event);
} else if (event.type == SWT.Paint) {
onPaint(event);
} else if (event.type == SWT.Dispose) {
onDispose(event);
}
}
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
Point clientAreaSize = calculateClientAreaSize();
Rectangle boundsWithTrim = computeTrim(0, 0, clientAreaSize.x,
clientAreaSize.y);
return new Point(boundsWithTrim.width, boundsWithTrim.height);
}
@Override
public void layout(boolean changed) {
for (StripItemController itemController : itemControllers) {
itemController.setBounds(calculateItemBounds(itemController
.getItem()));
}
}
@Override
public void setLayout(Layout layout) {
throw new UnsupportedOperationException();
}
@Override
public void setLayoutDeferred(boolean defer) {
throw new UnsupportedOperationException();
}
public int getItemCount() {
return itemControllers.size();
}
public StripItem[] getItems() {
List<StripItem> items = new ArrayList<StripItem>();
for (StripItemController itemController : itemControllers) {
items.add(itemController.getItem());
}
return items.toArray(new StripItem[items.size()]);
}
public int indexOf(StripItem item) {
if (item == null) {
throw new NullPointerException();
}
StripItemController itemController = getItemController(item);
if (itemController == null) {
return -1;
}
return itemControllers.indexOf(itemController);
}
public boolean contains(StripItem item) {
return indexOf(item) != -1;
}
protected void onSetData(Event event) {
StripItem item = (StripItem) event.item;
if (event.detail == SWT.INSERT) {
if (event.index < 0 || event.index > itemControllers.size()) {
event.index = itemControllers.size();
}
itemControllers.add(event.index, new StripItemController(item));
} else if (event.detail == SWT.DEL) {
StripItemController itemController = getItemController(item);
itemControllers.remove(itemController);
}
}
protected void onPaint(Event event) {
for (StripItemController itemController : itemControllers) {
drawItem(event.gc, itemController);
}
}
protected void onDispose(Event event) {
StripItem[] items = getItems();
for (StripItem item : items) {
item.dispose();
}
}
protected StripItemController getItemController(StripItem item) {
for (StripItemController itemController : itemControllers) {
if (itemController.getItem().equals(item)) {
return itemController;
}
}
return null;
}
protected Point calculateItemSize(StripItem item) {
if (!contains(item)) {
throw new IllegalArgumentException();
}
Point size = new Point(0, 0);
GC gc = new GC(this);
{
for (StripItemController itemController : itemControllers) {
if (itemController.getItem().getImage() != null) {
size.y = Math.max(size.y, itemController.getItem()
.getImage().getBounds().height);
}
if (itemController.getItem().getText() != null
&& !itemController.getItem().getText().isEmpty()) {
size.y = Math
.max(size.y, gc.stringExtent(itemController
.getItem().getText()).y);
}
size.y = Math.max(size.y, UIImageResource.T
.closeNormal10().getBounds().height);
}
if (item.getImage() != null) {
size.x += item.getImage().getBounds().width;
}
if (item.getText() != null && !item.getText().isEmpty()) {
if (item.getImage() != null) {
size.x += itemTextExtraSpaceBefore;
}
size.x += gc.stringExtent(item.getText()).x;
}
if ((item.getImage() != null)
|| (item.getText() != null && !item.getText().isEmpty())) {
size.x += itemCloseButtonExtraSpaceBefore;
}
size.x += UIImageResource.T.closeNormal10().getBounds().width;
size.x += itemMarginLeft;
size.x += itemMarginRight;
size.y += itemMarginTop;
size.y += itemMarginBottom;
}
gc.dispose();
return size;
}
protected Point calculateClientAreaSize() {
Point clientAreaSize = new Point(0, 0);
for (StripItemController itemController : itemControllers) {
Point itemSize = calculateItemSize(itemController.getItem());
clientAreaSize.x += itemSize.x;
clientAreaSize.y = Math.max(clientAreaSize.y, itemSize.y);
}
clientAreaSize.x += itemSpacing * (itemControllers.size() - 1);
clientAreaSize.x += barMarginLeft;
clientAreaSize.x += barMarginRight;
clientAreaSize.y += barMarginTop;
clientAreaSize.y += barMarginBottom;
return clientAreaSize;
}
protected Rectangle calculateItemBounds(StripItem item) {
if (!contains(item)) {
throw new IllegalArgumentException();
}
Rectangle bounds = new Rectangle(0, 0, 0, 0);
bounds.x += barMarginLeft;
bounds.y += barMarginTop;
for (StripItemController itemController : itemControllers) {
Point itemSize = calculateItemSize(itemController.getItem());
bounds.height = Math.max(bounds.height, itemSize.y);
}
for (StripItemController itemController : itemControllers) {
Point itemSize = calculateItemSize(itemController.getItem());
if (itemController.getItem().equals(item)) {
bounds.width = itemSize.x;
break;
} else {
bounds.x += itemSize.x;
bounds.x += itemSpacing;
}
}
return bounds;
}
protected Rectangle calculateItemImageBounds(StripItem item,
Rectangle itemBounds) {
if (!contains(item)) {
throw new IllegalArgumentException();
}
Rectangle bounds = new Rectangle(itemBounds.x, itemBounds.y,
itemBounds.width, itemBounds.height);
bounds.x += itemMarginLeft;
bounds.y += itemBounds.height / 2;
bounds.width = 0;
bounds.height = 0;
if (item.getImage() != null) {
Rectangle imageBounds = item.getImage().getBounds();
bounds.y -= imageBounds.height / 2;
bounds.width = imageBounds.width;
bounds.height = imageBounds.height;
}
return bounds;
}
protected Rectangle calculateItemTextBounds(StripItem item,
Rectangle itemBounds) {
if (!contains(item)) {
throw new IllegalArgumentException();
}
Rectangle bounds = calculateItemImageBounds(item, itemBounds);
bounds.x += bounds.width;
bounds.y += bounds.height / 2;
bounds.width = 0;
bounds.height = 0;
if (item.getText() != null && !item.getText().isEmpty()) {
if (item.getImage() != null) {
bounds.x += itemTextExtraSpaceBefore;
}
GC gc = new GC(this);
{
Point textSize = gc.stringExtent(item.getText());
bounds.y -= textSize.y / 2;
bounds.width = textSize.x;
bounds.height = textSize.y;
}
gc.dispose();
}
return bounds;
}
protected Rectangle calculateItemCloseButtonBounds(StripItem item,
Rectangle itemBounds) {
if (!contains(item)) {
throw new IllegalArgumentException();
}
Rectangle bounds = calculateItemTextBounds(item, itemBounds);
bounds.x += bounds.width;
bounds.y += bounds.height / 2;
bounds.width = 0;
bounds.height = 0;
if ((item.getImage() != null)
|| (item.getText() != null && !item.getText().isEmpty())) {
bounds.x += itemCloseButtonExtraSpaceBefore;
}
Rectangle closeButtonImageBounds = UIImageResource.T
.closeNormal10().getBounds();
bounds.y -= closeButtonImageBounds.height / 2;
bounds.width = closeButtonImageBounds.width;
bounds.height = closeButtonImageBounds.height;
return bounds;
}
protected void drawItem(GC gc, StripItemController itemController) {
drawItemBackground(gc, itemController);
drawItemImage(gc, itemController);
drawItemText(gc, itemController);
drawItemCloseButton(gc, itemController);
drawItemFrame(gc, itemController);
}
protected void drawItemBackground(GC gc, StripItemController itemController) {
Display display = getDisplay();
Color oldBackground = gc.getBackground();
Color newBackground = new Color(display, itemController.getBackground());
gc.setBackground(newBackground);
{
Rectangle bounds = itemController.getBounds();
gc.fillRoundRectangle(bounds.x, bounds.y, bounds.width - 1,
bounds.height - 1, itemArcSize, itemArcSize);
}
gc.setBackground(oldBackground);
newBackground.dispose();
}
protected void drawItemImage(GC gc, StripItemController itemController) {
if (itemController.getItem().getImage() == null) {
return;
}
Rectangle bounds = calculateItemImageBounds(itemController.getItem(),
itemController.getBounds());
gc.drawImage(itemController.getItem().getImage(), bounds.x, bounds.y);
}
protected void drawItemText(GC gc, StripItemController itemController) {
if (itemController.getItem().getText() == null
|| itemController.getItem().getText().isEmpty()) {
return;
}
Rectangle bounds = calculateItemTextBounds(itemController.getItem(),
itemController.getBounds());
gc.drawText(itemController.getItem().getText(), bounds.x, bounds.y);
}
protected void drawItemCloseButton(GC gc, StripItemController itemController) {
Rectangle bounds = calculateItemCloseButtonBounds(
itemController.getItem(), itemController.getBounds());
gc.drawImage(UIImageResource.T.closeNormal10(), bounds.x,
bounds.y);
}
protected void drawItemFrame(GC gc, StripItemController itemController) {
Display display = getDisplay();
Color oldForeground = gc.getForeground();
Color newForeground = display
.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
gc.setForeground(newForeground);
{
Rectangle bounds = itemController.getBounds();
gc.drawRoundRectangle(bounds.x, bounds.y, bounds.width - 1,
bounds.height - 1, itemArcSize, itemArcSize);
}
gc.setForeground(oldForeground);
}
public static void main(String[] args) {
Display display = Display.getDefault();
Shell shell = new Shell(display);
{
GridLayout layout = new GridLayout();
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
layout.marginWidth = 0;
layout.marginHeight = 0;
shell.setLayout(layout);
}
StripBar bar = new StripBar(shell, SWT.DOUBLE_BUFFERED | SWT.BORDER);
{
GridData data = new GridData();
data.horizontalAlignment = SWT.FILL;
data.verticalAlignment = SWT.FILL;
data.grabExcessHorizontalSpace = true;
bar.setLayoutData(data);
}
{
StripItem item1 = new StripItem(bar, SWT.NONE);
item1.setText("Item 1");
StripItem item2 = new StripItem(bar, SWT.NONE);
item2.setImage(UIImageResource.T.addContact16());
StripItem item3 = new StripItem(bar, SWT.NONE);
StripItem item0 = new StripItem(bar, SWT.NONE, 0);
item0.setText("Item 0");
item0.setImage(UIImageResource.T.about16());
}
bar.layout();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}