package com.peterhi.ui.stripbar7;
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.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Transform;
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 {
public static enum RenderType {
HORIZONTAL,
VERTICAL_ALL,
VERTICAL_TEXTONLY;
}
private final List<StripItem> stripItems = new ArrayList<StripItem>();
private final int horizontalMargin = 5;
private final int verticalMargin = 5;
private final int horizontalInset = 10;
private final int verticalInset = 5;
private final int spacing = 5;
private final int textIndent = 5;
private final int closeButtonIndent = 5;
private final int arcSize = 6;
private RenderType renderType = RenderType.HORIZONTAL;
public StripBar(Composite parent, int style) {
super(parent, style);
addListener(SWT.Dispose, this);
addListener(SWT.Paint, this);
}
public int getItemCount() {
return stripItems.size();
}
public int indexOf(StripItem stripItem) {
return stripItems.indexOf(stripItem);
}
public boolean contains(StripItem stripItem) {
int index = indexOf(stripItem);
if (index < 0) {
return false;
} else {
return true;
}
}
public StripItem[] getStripItems() {
return stripItems.toArray(new StripItem[stripItems.size()]);
}
@Override
public void handleEvent(Event event) {
if (!equals(event.widget)) {
return;
}
if (event.type == SWT.Dispose) {
onDispose(event);
} else if (event.type == SWT.Paint) {
onPaint(event);
}
}
@Override
public Point computeSize(int widthHint, int heightHint, boolean changed) {
Rectangle boundsWithTrim = computeBoundsWithTrim(getRenderType());
return new Point(boundsWithTrim.width, boundsWithTrim.height);
}
@Override
public void layout(boolean changed) {
for (StripItem stripItem : stripItems) {
Rectangle stripItemBounds = computeStripItemBounds(stripItem, renderType);
stripItem.setBounds(stripItemBounds, false);
}
}
@Override
public void setLayout(Layout layout) {
throw new UnsupportedOperationException();
}
@Override
public void setLayoutDeferred(boolean deferred) {
throw new UnsupportedOperationException();
}
public RenderType getRenderType() {
return renderType;
}
public void setRenderType(RenderType value) {
if (value == null) {
throw new NullPointerException();
}
renderType = value;
}
protected void onDispose(Event event) {
StripItem[] stripItems = getStripItems();
for (StripItem stripItem : stripItems) {
stripItem.dispose();
}
}
protected void onPaint(Event event) {
GC gc = event.gc;
StripItem[] stripItemsInPaintOrder = getStripItemsInPaintOrder();
for (StripItem stripItemInPaintOrder : stripItemsInPaintOrder) {
paintStripItem(gc, stripItemInPaintOrder);
}
}
void addStripItemInternal(StripItem stripItem, int index) {
if (stripItem == null) {
throw new NullPointerException();
}
if (contains(stripItem)) {
throw new IllegalArgumentException("Adding an item that already contains.");
}
if (index < 0) {
index = getItemCount();
}
if (index > getItemCount()) {
index = getItemCount();
}
stripItems.add(index, stripItem);
}
void removeStripItemInternal(StripItem stripItem) {
if (stripItem == null) {
throw new NullPointerException();
}
if (!contains(stripItem)) {
throw new IllegalArgumentException("Removing an item that doesn't contain.");
}
stripItems.remove(stripItem);
}
private Rectangle computeBoundsWithTrim(RenderType renderType) {
if (renderType == null) {
throw new NullPointerException();
}
Point size = new Point(0, 0);
for (StripItem stripItem : stripItems) {
Rectangle stripItemBounds = computeStripItemBounds(stripItem, renderType);
if (renderType == RenderType.HORIZONTAL) {
size.x += stripItemBounds.width;
size.y = Math.max(size.y, stripItemBounds.height);
} else {
size.x = Math.max(size.x, stripItemBounds.width);
size.y += stripItemBounds.height;
}
}
if (renderType == RenderType.HORIZONTAL) {
size.x += horizontalMargin * 2;
size.x += spacing * (getItemCount() - 1);
size.y += verticalMargin * 2;
} else {
size.x += verticalMargin * 2;
size.y += horizontalMargin * 2;
size.y += spacing * (getItemCount() - 1);
}
Rectangle boundsWithTrim = computeTrim(0, 0, size.x, size.y);
return boundsWithTrim;
}
private Rectangle computeStripItemImageBounds(StripItem stripItem, Rectangle refBounds, RenderType renderType) {
if (stripItem == null) {
throw new NullPointerException();
}
if (refBounds == null) {
throw new NullPointerException();
}
if (renderType == null) {
throw new NullPointerException();
}
Rectangle imageBounds = new Rectangle(0, 0, 0, 0);
if (renderType == RenderType.HORIZONTAL) {
imageBounds.x = refBounds.x + horizontalInset;
imageBounds.y = refBounds.y + refBounds.height / 2;
} else {
imageBounds.x = refBounds.x + refBounds.width / 2;
imageBounds.y = refBounds.y + verticalInset;
}
if (stripItem.hasImage()) {
Point imageSize = stripItem.getImageSize();
if (renderType == RenderType.VERTICAL_ALL) {
imageBounds.x -= imageSize.y / 2;
imageBounds.width = imageSize.y;
imageBounds.height = imageSize.x;
} else if (renderType == RenderType.VERTICAL_TEXTONLY) {
imageBounds.x -= imageSize.x / 2;
imageBounds.width = imageSize.x;
imageBounds.height = imageSize.y;
} else {
imageBounds.y -= imageSize.y / 2;
imageBounds.width = imageSize.x;
imageBounds.height = imageSize.y;
}
}
return imageBounds;
}
private Rectangle computeStripItemTextBounds(StripItem stripItem, Rectangle refBounds, RenderType renderType) {
if (stripItem == null) {
throw new NullPointerException();
}
if (refBounds == null) {
throw new NullPointerException();
}
if (renderType == null) {
throw new NullPointerException();
}
Rectangle imageBounds = computeStripItemImageBounds(stripItem, refBounds, renderType);
Rectangle textBounds = new Rectangle(0, 0, 0, 0);
if (renderType == RenderType.HORIZONTAL) {
textBounds.x = imageBounds.x + imageBounds.width;
textBounds.y = imageBounds.y + imageBounds.height / 2;
} else {
textBounds.x = imageBounds.x + imageBounds.width / 2;
textBounds.y = imageBounds.y + imageBounds.height;
}
if (stripItem.hasText()) {
if (stripItem.hasImage()) {
if (renderType == RenderType.HORIZONTAL) {
textBounds.x += textIndent;
} else {
textBounds.y += textIndent;
}
}
Point textSize = stripItem.getTextSize();
if (renderType == RenderType.HORIZONTAL) {
textBounds.y -= textSize.y / 2;
textBounds.width = textSize.x;
textBounds.height = textSize.y;
} else {
textBounds.x -= textSize.x / 2;
textBounds.width = textSize.y;
textBounds.height = textSize.x;
}
}
return textBounds;
}
private Rectangle computeStripItemBounds(StripItem stripItem, RenderType renderType) {
if (stripItem == null) {
throw new NullPointerException();
}
if (renderType == null) {
throw new NullPointerException();
}
Rectangle stripItemBounds = new Rectangle(0, 0, 0, 0);
if (renderType == RenderType.HORIZONTAL) {
stripItemBounds.x += horizontalMargin;
stripItemBounds.y += verticalMargin;
} else {
stripItemBounds.x += verticalMargin;
stripItemBounds.y += horizontalMargin;
}
for (StripItem aStripItem : stripItems) {
Point anImageSize = aStripItem.getImageSize();
Point aTextSize = aStripItem.getTextSize();
Point aCloseButtonSize = getCloseButtonSize();
int valueToSet = horizontalInset * 2;
if (renderType == RenderType.VERTICAL_TEXTONLY) {
valueToSet += anImageSize.y;
valueToSet += aTextSize.x;
valueToSet += aCloseButtonSize.y;
} else {
valueToSet += anImageSize.x;
valueToSet += aTextSize.x;
valueToSet += aCloseButtonSize.x;
}
if (aStripItem.hasImage()) {
valueToSet += textIndent;
}
if (aStripItem.hasImage() || aStripItem.hasText()) {
valueToSet += closeButtonIndent;
}
if (renderType == RenderType.HORIZONTAL) {
if (aStripItem.equals(stripItem)) {
stripItemBounds.width = valueToSet;
break;
} else {
stripItemBounds.x += valueToSet;
stripItemBounds.x += spacing;
}
} else {
if (aStripItem.equals(stripItem)) {
stripItemBounds.height = valueToSet;
break;
} else {
stripItemBounds.y += valueToSet;
stripItemBounds.y += spacing;
}
}
}
for (StripItem aStripItem : stripItems) {
Point anImageSize = aStripItem.getImageSize();
Point aTextSize = aStripItem.getTextSize();
Point aCloseButtonSize = getCloseButtonSize();
if (renderType == RenderType.VERTICAL_ALL) {
stripItemBounds.width = Math.max(stripItemBounds.width, anImageSize.y);
stripItemBounds.width = Math.max(stripItemBounds.width, aTextSize.y);
stripItemBounds.width = Math.max(stripItemBounds.width, aCloseButtonSize.y);
} else if (renderType == RenderType.VERTICAL_TEXTONLY) {
stripItemBounds.width = Math.max(stripItemBounds.width, anImageSize.x);
stripItemBounds.width = Math.max(stripItemBounds.width, aTextSize.y);
stripItemBounds.width = Math.max(stripItemBounds.width, aCloseButtonSize.x);
} else {
stripItemBounds.height = Math.max(stripItemBounds.height, anImageSize.y);
stripItemBounds.height = Math.max(stripItemBounds.height, aTextSize.y);
stripItemBounds.height = Math.max(stripItemBounds.height, aCloseButtonSize.y);
}
}
if (renderType == RenderType.HORIZONTAL) {
stripItemBounds.height += verticalInset * 2;
} else {
stripItemBounds.width += verticalInset * 2;
}
return stripItemBounds;
}
private Point getCloseButtonSize() {
Image closeButtonImage = getCloseButtonImage(false);
Rectangle closeButtonImageBounds = closeButtonImage.getBounds();
return new Point(closeButtonImageBounds.width, closeButtonImageBounds.height);
}
private Image getCloseButtonImage(boolean highlightOrNormalImage) {
Image closeButtonImage;
if (highlightOrNormalImage) {
closeButtonImage = UIImageResource.T.closeHighlight10();
} else {
closeButtonImage = UIImageResource.T.closeNormal10();
}
return closeButtonImage;
}
private StripItem[] getStripItemsInPaintOrder() {
// TODO: remove this method stub, and implement real logic here
return getStripItems();
}
private void paintStripItem(GC gc, StripItem stripItem) {
paintStripItemBackground(gc, stripItem);
paintStripItemImage(gc, stripItem);
// paintStripItemText(gc, stripItem);
paintStripItemCloseButton(gc, stripItem);
paintStripItemBorder(gc, stripItem);
}
private void paintStripItemBackground(GC gc, StripItem stripItem) {
}
private void paintStripItemImage(GC gc, StripItem stripItem) {
if (!stripItem.hasImage()) {
return;
}
Rectangle bounds = stripItem.getBounds(true);
Rectangle imageBounds = computeStripItemImageBounds(stripItem, bounds, renderType);
Display display = getDisplay();
Transform transform = new Transform(display);
if (renderType == renderType.VERTICAL_ALL) {
transform.translate(imageBounds.x, imageBounds.y);
transform.rotate(-90);
transform.translate(-imageBounds.x, -imageBounds.y);
transform.translate(-imageBounds.height, 0);
} else {
}
gc.setTransform(transform);
Image image = stripItem.getImage();
gc.drawImage(image, imageBounds.x, imageBounds.y);
gc.setTransform(null);
transform.dispose();
}
private void paintStripItemText(GC gc, StripItem stripItem) {
if (!stripItem.hasText()) {
return;
}
Rectangle bounds = stripItem.getBounds(true);
Rectangle textBounds = computeStripItemTextBounds(stripItem, bounds, renderType);
Display display = getDisplay();
Color oldForeground = gc.getForeground();
Color newForeground = new Color(display, stripItem.getForeground(true));
gc.setForeground(newForeground);
String text = stripItem.getText();
gc.drawText(text, textBounds.x, textBounds.y, true);
gc.setForeground(oldForeground);
newForeground.dispose();
}
private void paintStripItemCloseButton(GC gc, StripItem stripItem) {
}
private void paintStripItemBorder(GC gc, StripItem stripItem) {
Rectangle bounds = stripItem.getBounds(true);
bounds.width --;
bounds.height --;
Display display = getDisplay();
Color oldForeground = gc.getForeground();
Color newForeground = display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
gc.setForeground(newForeground);
gc.drawRoundRectangle(bounds.x, bounds.y, bounds.width, bounds.height, arcSize, arcSize);
gc.setForeground(oldForeground);
}
public static void main(String[] args) {
Display display = Display.getDefault();
Shell shell = new Shell(display);
StripBar stripBar = new StripBar(shell, SWT.DOUBLE_BUFFERED | SWT.BORDER);
GridLayout shellLayout = new GridLayout();
GridData stripBarLayoutData = new GridData();
shellLayout.horizontalSpacing = 0;
shellLayout.verticalSpacing = 0;
shellLayout.marginWidth = 0;
shellLayout.marginHeight = 0;
shell.setLayout(shellLayout);
stripBarLayoutData.horizontalAlignment = SWT.FILL;
stripBarLayoutData.verticalAlignment = SWT.FILL;
stripBarLayoutData.grabExcessVerticalSpace = true;
stripBar.setLayoutData(stripBarLayoutData);
stripBar.setRenderType(RenderType.VERTICAL_ALL);
StripItem stripItem0 = new StripItem(stripBar, SWT.NONE);
StripItem stripItem2 = new StripItem(stripBar, SWT.NONE);
StripItem stripItem3 = new StripItem(stripBar, SWT.NONE);
StripItem stripItem1 = new StripItem(stripBar, SWT.NONE, 1);
stripItem0.setText("Item 0");
stripItem0.setImage(UIImageResource.T.about16());
stripItem2.setImage(UIImageResource.T.foo());
stripItem1.setText("Item 1");
stripBar.layout();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}