package com.peterhi.ui.bar2;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
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.RGB;
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.Item;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.jdesktop.core.animation.timing.Animator;
import org.jdesktop.core.animation.timing.TimingTargetAdapter;
import com.peterhi.ui.UIImageResource;
import com.peterhi.ui.UI;
@Deprecated
public class StripBar2 extends Canvas implements Listener {
public static class StripItem extends Item implements Listener {
public static final int NONE = 0;
public static final int HOVERED = 1;
public static final int CLICKED = 2;
public static final int SELECTED = 3;
public static final RGB NONE_RGB = Display.getDefault().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND).getRGB();
public static final RGB HOVERED_RGB = new RGB(72, 118, 255);
public static final RGB CLICKED_RGB = new RGB(65, 105, 225);
public static final RGB SELECTED_RGB = new RGB(67, 110, 238);
private Animator animator;
private StripBar2 parent;
private int state;
RGB currentForeground;
RGB currentBackground;
public StripItem(StripBar2 parent, int style) {
super(parent, style);
init(parent, style, -1);
}
public StripItem(StripBar2 parent, int style, int index) {
super(parent, style, index);
init(parent, style, index);
}
private void init(StripBar2 parent, int style, int index) {
this.parent = parent;
parent.add(this, index);
addListener(SWT.Dispose, this);
}
@Override
public void handleEvent(Event event) {
if (event.widget == this && event.type == SWT.Dispose) {
animator.cancel();
}
}
public int getState() {
return state;
}
public void setState(int value) {
if (value != NONE && value != HOVERED && value != CLICKED && value != SELECTED) {
throw new IllegalArgumentException();
}
if (state != value) {
if ((state == NONE && value == HOVERED) || (state == HOVERED && value == NONE)) {
final RGB from;
final RGB to;
currentForeground = null;
if (currentBackground != null) {
from = currentBackground;
} else {
if (state == HOVERED) {
from = HOVERED_RGB;
} else if (state == CLICKED) {
from = CLICKED_RGB;
} else if (state == SELECTED) {
from = SELECTED_RGB;
} else {
Color background = getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
from = background.getRGB();
}
}
if (value == HOVERED) {
to = HOVERED_RGB;
} else if (value == CLICKED) {
to = CLICKED_RGB;
} else if (value == SELECTED) {
to = SELECTED_RGB;
} else {
Color background = getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
to = background.getRGB();
}
if (animator != null) {
animator.cancel();
}
animator = new Animator.Builder().addTarget(new TimingTargetAdapter() {
@Override
public void timingEvent(Animator source, double fraction) {
int rDiff = to.red - from.red;
int gDiff = to.green - from.green;
int bDiff = to.blue - from.blue;
rDiff = (int )Math.round(rDiff * fraction);
gDiff = (int )Math.round(gDiff * fraction);
bDiff = (int )Math.round(bDiff * fraction);
currentBackground = new RGB(from.red + rDiff, from.green + gDiff, from.blue + bDiff);
Rectangle bounds = getBounds();
parent.redraw(bounds.x, bounds.y, bounds.width, bounds.height, true);
}
@Override
public void end(Animator source) {
currentBackground = to;
Rectangle bounds = getBounds();
parent.redraw(bounds.x, bounds.y, bounds.width, bounds.height, true);
animator = null;
}
}).setDuration(200, TimeUnit.MILLISECONDS).build();
state = value;
animator.start();
} else {
if (animator != null) {
animator.cancel();
}
if (value == CLICKED) {
currentBackground = CLICKED_RGB;
} else if (value == SELECTED) {
currentBackground = SELECTED_RGB;
if (state == CLICKED) {
currentForeground = getDisplay().getSystemColor(SWT.COLOR_WHITE).getRGB();
}
} else if (value == HOVERED) {
currentBackground = HOVERED_RGB;
} else if (value == NONE) {
currentBackground = NONE_RGB;
currentForeground = null;
}
state = value;
Rectangle bounds = getBounds();
parent.redraw(bounds.x, bounds.y, bounds.width, bounds.height, true);
if ((parent.getStyle() & SWT.MULTI) != SWT.MULTI) {
StripItem[] otherItems = parent.getItems();
for (StripItem otherItem : otherItems) {
if (otherItem.equals(this)) {
continue;
}
if (otherItem.getState() == SELECTED) {
otherItem.setState(NONE);
}
}
}
}
}
}
public StripBar2 getParent() {
return parent;
}
public Rectangle getBounds() {
return parent.getBounds(this);
}
public Rectangle getImageBounds() {
return parent.getImageBounds(this);
}
public Rectangle getTextBounds() {
return parent.getTextBounds(this);
}
public Rectangle getCloseButtonBounds() {
return parent.getCloseButtonBounds(this);
}
}
private int spacing = 6;
private List<StripItem> items = new ArrayList<StripItem>();
private StripItem dragged;
private StripItem selected;
private int selectedState;
public StripBar2(Composite parent, int style) {
super(parent, style);
addListener(SWT.Paint, this);
addListener(SWT.MouseEnter, this);
addListener(SWT.MouseMove, this);
addListener(SWT.MouseExit, this);
addListener(SWT.MouseDown, this);
addListener(SWT.MouseUp, this);
}
@Override
public void handleEvent(Event event) {
if (event.widget == this && event.type == SWT.Paint) {
for (int i = 0; i < items.size(); i++) {
StripItem item = items.get(i);
paintStripItem(event.gc, item);
}
} else if (event.widget == this && event.type == SWT.MouseEnter) {
checkHover(event.x, event.y);
} else if (event.widget == this && event.type == SWT.MouseMove) {
checkHover(event.x, event.y);
} else if (event.widget == this && event.type == SWT.MouseExit) {
checkHover(event.x, event.y);
} else if (event.widget == this && event.type == SWT.MouseDown) {
checkDown(event.x, event.y);
} else if (event.widget == this && event.type == SWT.MouseMove) {
} else if (event.widget == this && event.type == SWT.MouseUp) {
checkUp(event.x, event.y);
}
}
private void checkHover(int x, int y) {
for (int i = 0; i < items.size(); i++) {
StripItem item = items.get(i);
Rectangle bounds = item.getBounds();
if (bounds.contains(x, y)) {
if (item.getState() != StripItem.SELECTED && item.getState() != StripItem.CLICKED) {
item.setState(StripItem.HOVERED);
}
} else {
if (item.getState() != StripItem.SELECTED && item.getState() != StripItem.CLICKED) {
item.setState(StripItem.NONE);
}
}
}
}
private void checkDown(int x, int y) {
for (int i = 0; i < items.size(); i++) {
StripItem item = items.get(i);
Rectangle bounds = item.getBounds();
if (bounds.contains(x, y)) {
selectedState = item.getState();
item.setState(StripItem.CLICKED);
dragged = item;
break;
}
}
}
private void checkUp(int x, int y) {
if (dragged != null) {
if (selectedState == StripItem.SELECTED) {
dragged.currentForeground = null;
dragged.setState(StripItem.HOVERED);
selected = null;
} else {
selected = dragged;
selected.setState(StripItem.SELECTED);
}
dragged = null;
selectedState = StripItem.NONE;
}
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
Point size = new Point(spacing, 0);
for (int i = 0; i < items.size(); i++) {
StripItem item = items.get(i);
Rectangle bounds = item.getBounds();
size.x += bounds.width;
size.x += spacing;
size.y = Math.max(size.y, bounds.height);
}
size.y += spacing * 2;
Rectangle bounds = computeTrim(0, 0, size.x, size.y);
size.x = bounds.width;
size.y = bounds.height;
return size;
}
public int getItemCount() {
return items.size();
}
public StripItem getItem(int index) {
return items.get(index);
}
public int indexOf(StripItem item) {
return items.indexOf(item);
}
public StripItem[] getItems() {
return items.toArray(new StripItem[items.size()]);
}
void add(StripItem item, int index) {
if (index == -1) {
items.add(item);
} else {
items.add(index, item);
}
}
Rectangle getBounds(StripItem item) {
GC gc = new GC(this);
Rectangle bounds = new Rectangle(spacing, spacing, 0, 0);
for (int i = 0; i < items.size(); i++) {
StripItem anItem = items.get(i);
if (anItem.getImage() != null) {
Rectangle imageBounds = anItem.getImage().getBounds();
bounds.height = Math.max(bounds.height, imageBounds.height);
}
if (anItem.getText() != null && !anItem.getText().isEmpty()) {
Point textSize = gc.stringExtent(anItem.getText());
bounds.height = Math.max(bounds.height, textSize.y);
}
Image closeButtonImage = UIImageResource.T.closeNormal10();
Rectangle closeButtonImageBounds = closeButtonImage.getBounds();
bounds.height = Math.max(bounds.height, closeButtonImageBounds.height);
}
bounds.height += spacing * 2;
for (int i = 0; i < items.size(); i++) {
StripItem anItem = items.get(i);
int extent = spacing * 2;
if (anItem.getImage() != null) {
Rectangle imageBounds = anItem.getImage().getBounds();
extent += imageBounds.width;
}
if (anItem.getText() != null && !anItem.getText().isEmpty()) {
if (anItem.getImage() != null) {
extent += spacing;
}
Point textSize = gc.stringExtent(anItem.getText());
extent += textSize.x;
}
if (anItem.getImage() != null || (anItem.getText() != null && !anItem.getText().isEmpty())) {
extent += spacing;
}
Image closeButtonImage = UIImageResource.T.closeNormal10();
Rectangle closeButtonImageBounds = closeButtonImage.getBounds();
extent += closeButtonImageBounds.width;
if (anItem.equals(item)) {
bounds.width = extent;
break;
} else {
bounds.x += extent;
bounds.x += spacing;
}
}
gc.dispose();
return bounds;
}
Rectangle getImageBounds(StripItem item) {
Rectangle bounds = item.getBounds();
Rectangle result = new Rectangle(0, 0, 0, 0);
result.x = bounds.x + spacing;
result.y = bounds.y + bounds.height / 2;
if (item.getImage() != null) {
Rectangle imageBounds = item.getImage().getBounds();
result.y -= imageBounds.height / 2;
result.width = imageBounds.width;
result.height = imageBounds.height;
}
return result;
}
Rectangle getTextBounds(StripItem item) {
Rectangle bounds = item.getImageBounds();
Rectangle result = new Rectangle(0, 0, 0, 0);
result.x = bounds.x + bounds.width;
result.y = bounds.y + bounds.height / 2;
if (item.getText() != null && !item.getText().isEmpty()) {
if (item.getImage() != null) {
result.x += spacing;
}
GC gc = new GC(this);
Point textSize = gc.stringExtent(item.getText());
result.y -= textSize.y / 2;
result.width = textSize.x;
result.height = textSize.y;
gc.dispose();
}
return result;
}
Rectangle getCloseButtonBounds(StripItem item) {
Rectangle bounds = item.getTextBounds();
Rectangle result = new Rectangle(0, 0, 0, 0);
result.x = bounds.x + bounds.width;
result.y = bounds.y + bounds.height / 2;
if (item.getImage() != null || (item.getText() != null && !item.getText().isEmpty())) {
result.x += spacing;
}
Image closeButtonImage = UIImageResource.T.closeNormal10();
Rectangle closeButtonImageBounds = closeButtonImage.getBounds();
result.y -= closeButtonImageBounds.height / 2;
result.width = closeButtonImageBounds.width;
result.height = closeButtonImageBounds.height;
return result;
}
private void paintStripItem(GC gc, StripItem item) {
paintStripItemBackground(gc, item);
paintStripItemImage(gc, item);
paintStripItemText(gc, item);
paintStripItemCloseButton(gc, item);
paintStripItemFrame(gc, item);
}
private void paintStripItemBackground(GC gc, StripItem item) {
if (item.currentBackground != null) {
Rectangle bounds = item.getBounds();
Color currentColor = new Color(getDisplay(), item.currentBackground);
Color oldBackground = gc.getBackground();
gc.setBackground(currentColor);
gc.fillRectangle(bounds);
gc.setBackground(oldBackground);
currentColor.dispose();
}
}
private void paintStripItemImage(GC gc, StripItem item) {
if (item.getImage() != null) {
Rectangle bounds = item.getImageBounds();
gc.drawImage(item.getImage(), bounds.x, bounds.y);
}
}
private void paintStripItemText(GC gc, StripItem item) {
if (item.getText() != null && !item.getText().isEmpty()) {
Color oldForeground = gc.getForeground();
Color newForeground = null;
if (item.currentForeground != null) {
newForeground = new Color(getDisplay(), item.currentForeground);
gc.setForeground(newForeground);
}
Rectangle bounds = item.getTextBounds();
gc.drawText(item.getText(), bounds.x, bounds.y, true);
gc.setForeground(oldForeground);
if (newForeground != null) {
newForeground.dispose();
}
}
}
private void paintStripItemCloseButton(GC gc, StripItem item) {
Rectangle bounds = item.getCloseButtonBounds();
gc.drawImage(UIImageResource.T.closeNormal10(), bounds.x, bounds.y);
}
private void paintStripItemFrame(GC gc, StripItem item) {
Rectangle bounds = item.getBounds();
Color oldForeground = gc.getForeground();
Color newForeground = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
gc.setForeground(newForeground);
gc.drawRectangle(bounds.x, bounds.y, bounds.width - 1, bounds.height);
gc.setForeground(oldForeground);
}
public static void main(String[] args) {
UI.initialize();
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);
StripBar2 bar = new StripBar2(shell, SWT.DOUBLE_BUFFERED);
GridData data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
data.grabExcessHorizontalSpace = true;
bar.setLayoutData(data);
{
StripItem item0 = new StripItem(bar, SWT.NONE);
item0.setText("Item 0");
item0.setImage(UIImageResource.T.about16());
StripItem item1 = new StripItem(bar, SWT.NONE);
item1.setText("Item 1");
StripItem item2 = new StripItem(bar, SWT.NONE, 0);
item2.setImage(UIImageResource.T.addContact16());
StripItem item3 = new StripItem(bar, SWT.NONE, 1);
}
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
UI.destroy();
}
}