package com.peterhi.ui.stripbar5;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
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 org.jdesktop.core.animation.timing.Animator;
import org.jdesktop.core.animation.timing.TimingTargetAdapter;
import org.jdesktop.swt.animation.timing.sources.SWTTimingSource;
import com.peterhi.ui.UIImageResource;
import com.peterhi.ui.UI;
public class StripBar extends Composite implements Listener {
public static final int LEFT = 5;
public static final int RIGHT = 5;
public static final int TOP = 5;
public static final int BOTTOM = 5;
public static final int SPACE = 5;
public static final int ITEM_LEFT = 8;
public static final int ITEM_RIGHT = 8;
public static final int ITEM_TOP = 5;
public static final int ITEM_BOTTOM = 5;
public static final int TEXT_INDENT = 5;
public static final int CLOSE_INDENT = 10;
public static final int ITEM_ARC = 6;
public static final int DRAG_THRESHOLD = 10;
private static final Comparator<StripItem> comp = new Comparator<StripItem>() {
@Override
public int compare(StripItem item, StripItem other) {
return item.getBounds().x - other.getBounds().x;
}
};
private final List<StripItem> items = new ArrayList<StripItem>();
private boolean animate;
private StripItem mouseItem;
private Point mouseDown;
private Point mouseMove;
private Point mouseOffset;
private Map<StripItem, Rectangle[]> boundsMap;
public StripBar(Composite parent, int style) {
super(parent, style);
addListener(SWT.Modify, this);
addListener(SWT.Dispose, this);
addListener(SWT.Paint, this);
addListener(SWT.MouseEnter, this);
addListener(SWT.MouseExit, this);
addListener(SWT.MouseDown, this);
addListener(SWT.MouseMove, this);
addListener(SWT.MouseUp, this);
}
@Override
public void handleEvent(Event event) {
if (equals(event.widget)) {
if (event.type == SWT.Modify) {
StripItem eventItem = (StripItem )event.item;
if (event.detail == SWT.INSERT) {
if (event.index < -1 || event.index > items.size()) {
throw new IllegalArgumentException();
}
if (event.index == -1) {
event.index = items.size();
}
items.add(event.index, eventItem);
} else if (event.detail == SWT.DEL) {
items.remove(eventItem);
}
} else if (event.type == SWT.Dispose) {
for (StripItem item : getItems()) {
item.dispose();
}
} else if (event.type == SWT.Paint) {
Display display = getDisplay();
GC gc = event.gc;
gc.setAdvanced(true);
gc.setAntialias(SWT.ON);
gc.setTextAntialias(SWT.ON);
StripItem[] itemsInPaintOrder = getItemsInPaintOrder();
for (StripItem eachItemInPaintOrder : itemsInPaintOrder) {
int state = eachItemInPaintOrder.getState();
if ((state & StripItem.OUTSIDE) == StripItem.OUTSIDE) {
continue;
}
if ((state & StripItem.DRAGGED) == StripItem.DRAGGED) {
gc.setAlpha(192);
}
Rectangle bounds = eachItemInPaintOrder.getRenderBounds();
Color oldForeground = gc.getForeground();
Color oldBackground = gc.getBackground();
Color newForeground;
Color newBackground;
newBackground = UI.newColor(eachItemInPaintOrder.getRenderBackground());
gc.setBackground(newBackground);
gc.fillRoundRectangle(bounds.x, bounds.y, bounds.width, bounds.height, ITEM_ARC, ITEM_ARC);
gc.setBackground(oldBackground);
newBackground.dispose();
if (eachItemInPaintOrder.hasImage()) {
Rectangle imageBounds = computeImageBounds(eachItemInPaintOrder, bounds);
gc.drawImage(eachItemInPaintOrder.getImage(), imageBounds.x, imageBounds.y);
}
if (eachItemInPaintOrder.hasText()) {
newForeground = UI.newColor(eachItemInPaintOrder.getRenderForeground());
gc.setForeground(newForeground);
Rectangle textBounds = computeTextBounds(eachItemInPaintOrder, bounds);
gc.drawText(eachItemInPaintOrder.getText(), textBounds.x, textBounds.y, true);
gc.setForeground(oldForeground);
newForeground.dispose();
}
Rectangle closeButtonBounds = computeCloseButtonBounds(eachItemInPaintOrder, bounds);
Image closeButtonImage = getCloseButtonImage(false);
gc.drawImage(closeButtonImage, closeButtonBounds.x, closeButtonBounds.y);
newForeground = display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
gc.setForeground(newForeground);
gc.drawRoundRectangle(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1, ITEM_ARC, ITEM_ARC);
gc.setForeground(oldForeground);
gc.setBackground(oldBackground);
gc.setAlpha(255);
}
} else if (event.type == SWT.MouseEnter) {
onProcessFocus(event.x, event.y);
} else if (event.type == SWT.MouseExit) {
onProcessFocus(event.x, event.y);
} else if (event.type == SWT.MouseDown) {
if (event.button == 1) {
if (!isBoundsAnimating()) {
if (mouseItem == null) {
mouseItem = getItem(StripItem.FOCUSED, false);
if (mouseItem != null) {
Rectangle itemBounds = mouseItem.getBounds();
int itemState = mouseItem.getState();
itemState |= StripItem.PRESSED;
mouseItem.setState(itemState, false);
mouseDown = new Point(event.x, event.y);
mouseMove = new Point(event.x, event.y);
mouseOffset = new Point(event.x - itemBounds.x, event.y - itemBounds.y);
boundsMap = new HashMap<StripItem, Rectangle[]>();
boolean after = false;
for (StripItem item : items) {
if (item.equals(mouseItem)) {
boundsMap.put(mouseItem, new Rectangle[] { mouseItem.getBounds(), mouseItem.getBounds() });
after = true;
}
if (after) {
Rectangle beforeBounds = item.getBounds();
beforeBounds.x -= SPACE + mouseItem.getBounds().width;
boundsMap.put(item, new Rectangle[] { beforeBounds, item.getBounds() });
} else {
Rectangle afterBounds = item.getBounds();
afterBounds.x += SPACE + mouseItem.getBounds().width;
boundsMap.put(item, new Rectangle[] { item.getBounds(), afterBounds });
}
}
}
}
}
}
} else if (event.type == SWT.MouseMove) {
onProcessFocus(event.x, event.y);
if (mouseItem != null) {
if (Math.abs(event.x - mouseDown.x) >= DRAG_THRESHOLD || Math.abs(event.y - mouseDown.y) >= DRAG_THRESHOLD) {
int itemState = mouseItem.getState();
itemState |= StripItem.DRAGGED;
mouseItem.setState(itemState, false);
}
int itemState = mouseItem.getState();
if ((itemState & StripItem.DRAGGED) == StripItem.DRAGGED) {
Rectangle clientArea = getClientArea();
// Moving outwards
if (!clientArea.contains(event.x, event.y)) {
if ((itemState & StripItem.OUTSIDE) != StripItem.OUTSIDE) {
itemState |= StripItem.OUTSIDE;
mouseItem.setState(itemState, false);
mouseItem.redraw(); // required manually because foreground & background don't change
StripItem[] itemsBehind = getItemsBehindOutwards(mouseItem.getBounds());
for (StripItem itemBehind : itemsBehind) {
Rectangle bounds = itemBehind.getBounds();
bounds.x -= SPACE + mouseItem.getBounds().width;
itemBehind.setBounds(bounds, isAnimate(), null);
}
}
}
// Moving inwards
if ((itemState & StripItem.OUTSIDE) == StripItem.OUTSIDE) {
if (clientArea.contains(event.x, event.y)) {
itemState &= ~StripItem.OUTSIDE;
mouseItem.setState(itemState, false);
mouseItem.redraw(); // required manually because foreground & background don't change
Rectangle boundsToCheck = mouseItem.getBounds();
boundsToCheck.x = event.x - mouseOffset.x;
StripItem[] itemsBehind = getItemsBehindInwards(boundsToCheck);
for (StripItem itemBehind : itemsBehind) {
Rectangle bounds = itemBehind.getBounds();
bounds.x += SPACE + boundsToCheck.width;
itemBehind.setBounds(bounds, isAnimate(), null);
}
Arrays.sort(itemsBehind, comp);
if (itemsBehind.length == 0) {
List<StripItem> copy = new ArrayList<StripItem>(items);
Collections.sort(copy, comp);
copy.remove(mouseItem);
Rectangle newBounds = mouseItem.getBounds();
newBounds.x = copy.get(copy.size() - 1).getBounds().x + copy.get(copy.size() - 1).getBounds().width + SPACE;
mouseItem.setBounds(newBounds, false, null);
} else {
Rectangle newBounds = mouseItem.getBounds();
newBounds.x = itemsBehind[0].getBounds().x - newBounds.width - SPACE;
mouseItem.setBounds(newBounds, false, null);
}
}
}
if ((itemState & StripItem.OUTSIDE) != StripItem.OUTSIDE && clientArea.contains(event.x, event.y)) {
if (isAnimate()) {
int delta = event.x - mouseMove.x;
StripItem[] affected = getAffectedItemsAnimated(mouseItem, delta);
Rectangle bounds = mouseItem.getBounds();
bounds.x = mouseDown.x - mouseOffset.x + (event.x - mouseDown.x);
if (bounds.x > getClientArea().width - SPACE - bounds.width) {
bounds.x = getClientArea().width - SPACE - bounds.width;
}
if (bounds.x < SPACE) {
bounds.x = SPACE;
}
mouseItem.setBounds(bounds, false, null);
int index = delta > 0 ? 0 : 1;
for (StripItem item : affected) {
Rectangle toSet = boundsMap.get(item)[index];
item.setBounds(toSet, true, new TimingTargetAdapter() {
@Override
public void end(Animator source) {
processFocus();
}
@Override
public void timingEvent(Animator source, double fraction) {
processFocus();
}
private void processFocus() {
Point location = getDisplay().getCursorLocation();
location = toControl(location);
onProcessFocus(location.x, location.y);
}
});
}
} else {
StripItem onItem = getItem(event.x, event.y);
if (onItem != null && !onItem.equals(mouseItem)) {
Rectangle mouseBounds = mouseItem.getBounds();
StripItem[] affected = getAffectedItemsNonAnimated(mouseItem, onItem);
if (onItem.getBounds().x > mouseItem.getBounds().x) {
for (StripItem aff : affected) {
Rectangle bounds = boundsMap.get(aff)[0];
aff.setBounds(bounds, false, null);
mouseBounds.x += bounds.width;
mouseBounds.x += SPACE;
}
} else {
for (StripItem aff : affected) {
Rectangle bounds = boundsMap.get(aff)[1];
aff.setBounds(bounds, false, null);
mouseBounds.x -= bounds.width;
mouseBounds.x -= SPACE;
}
}
mouseItem.setBounds(mouseBounds, false, null);
Point location = new Point(mouseBounds.x + mouseBounds.width / 2, mouseBounds.y + mouseBounds.height / 2);
location = toDisplay(location);
getDisplay().setCursorLocation(location);
}
}
}
}
mouseMove = new Point(event.x, event.y);
}
} else if (event.type == SWT.MouseUp) {
if (event.button == 1) {
if (mouseItem != null) {
int itemState = mouseItem.getState();
boolean wasSelected = (itemState & StripItem.SELECTED) == StripItem.SELECTED;
itemState &= ~StripItem.PRESSED;
if ((itemState & StripItem.DRAGGED) == StripItem.DRAGGED) {
itemState &= ~StripItem.DRAGGED;
} else {
if (isMultiSelect()) {
if (wasSelected) {
itemState &= ~StripItem.SELECTED;
} else {
itemState |= StripItem.SELECTED;
}
} else {
if (!wasSelected) {
itemState |= StripItem.SELECTED;
for (StripItem otherItem : items) {
int otherState = otherItem.getState();
otherState &= ~StripItem.SELECTED;
otherItem.setState(otherState, animate);
}
}
}
}
mouseItem.setState(itemState, false);
reorderItems();
if (isAnimate()) {
Rectangle compute = computeBounds(mouseItem);
mouseItem.setBounds(compute, true, new TimingTargetAdapter() {
@Override
public void end(Animator source) {
processFocus();
}
@Override
public void timingEvent(Animator source, double fraction) {
processFocus();
}
private void processFocus() {
Point location = getDisplay().getCursorLocation();
location = toControl(location);
onProcessFocus(location.x, location.y);
}
});
}
mouseItem = null;
mouseDown = null;
mouseMove = null;
mouseOffset = null;
}
}
}
}
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
Point internalSize = computeInternalSize();
Rectangle boundsWithTrim = computeTrim(0, 0, internalSize.x, internalSize.y);
return new Point(boundsWithTrim.width, boundsWithTrim.height);
}
@Override
public void layout(boolean changed) {
for (StripItem eachItem : items) {
Rectangle eachBounds = computeBounds(eachItem);
eachItem.setBounds(eachBounds, false, null);
}
}
@Override
public void setLayout(Layout layout) {
throw new UnsupportedOperationException();
}
@Override
public void setLayoutDeferred(boolean defer) {
throw new UnsupportedOperationException();
}
public boolean isMultiSelect() {
int style = getStyle();
boolean multi = (style & SWT.MULTI) == SWT.MULTI;
return multi;
}
public int indexOf(StripItem item) {
if (item == null) {
throw new NullPointerException();
}
return items.indexOf(item);
}
public boolean contains(StripItem item) {
return indexOf(item) >= 0;
}
public StripItem[] getItems() {
return items.toArray(new StripItem[items.size()]);
}
public StripItem[] getItems(int state, boolean exact) {
List<StripItem> itemsOfState = new ArrayList<StripItem>();
for (StripItem eachItem : items) {
if (exact) {
if (eachItem.getState() == state) {
itemsOfState.add(eachItem);
}
} else {
if ((eachItem.getState() & state) == state) {
itemsOfState.add(eachItem);
}
}
}
return itemsOfState.toArray(new StripItem[itemsOfState.size()]);
}
public StripItem getItem(int state, boolean exact) {
StripItem[] items = getItems(state, exact);
if (items.length == 0) {
return null;
}
return items[0];
}
public StripItem getItem(int index) {
return items.get(index);
}
public StripItem getItem(int x, int y) {
for (StripItem eachItem : items) {
Rectangle bounds = eachItem.getRenderBounds();
if (bounds.contains(x, y)) {
return eachItem;
}
}
return null;
}
public boolean isAnimate() {
return animate;
}
public void setAnimate(boolean value) {
animate = value;
}
protected void onProcessFocus(int x, int y) {
if (mouseItem != null) {
return;
}
StripItem oldItem = getItem(StripItem.FOCUSED, false);
StripItem newItem = getItem(x, y);
if (oldItem != null && newItem != null) {
if (oldItem.equals(newItem)) {
return;
}
}
if (oldItem != null) {
int itemState = oldItem.getState();
itemState &= ~StripItem.FOCUSED;
oldItem.setState(itemState, animate);
}
if (newItem != null) {
int itemState = newItem.getState();
itemState |= StripItem.FOCUSED;
newItem.setState(itemState, animate);
}
}
private Point computeInternalSize() {
Point internalSize = new Point(0, 0);
for (StripItem eachItem : items) {
Point eachSize = computeSize(eachItem);
internalSize.x += eachSize.x;
internalSize.y = Math.max(internalSize.y, eachSize.y);
}
internalSize.x += LEFT + SPACE * (items.size() - 1) + RIGHT;
internalSize.y += TOP + BOTTOM;
return internalSize;
}
private Point computeSize(StripItem item) {
if (item == null) {
throw new NullPointerException();
}
if (!items.contains(item)) {
throw new IllegalArgumentException();
}
Point size = new Point(0, 0);
if (item.hasImage()) {
size.x += item.getImageSize().x;
}
if (item.hasText()) {
if (item.hasImage()) {
size.x += TEXT_INDENT;
}
size.x += item.getTextSize().x;
}
if (item.hasImage() || item.hasText()) {
size.x += CLOSE_INDENT;
}
size.x += getCloseButtonSize().x;
for (StripItem eachItem : items) {
if (eachItem.hasImage()) {
size.y = Math.max(size.y, eachItem.getImageSize().y);
}
if (eachItem.hasText()) {
size.y = Math.max(size.y, eachItem.getTextSize().y);
}
size.y = Math.max(size.y, getCloseButtonSize().y);
}
size.x += ITEM_LEFT + ITEM_RIGHT;
size.y += ITEM_TOP + ITEM_BOTTOM;
return size;
}
private Rectangle computeBounds(StripItem item) {
if (item == null) {
throw new NullPointerException();
}
if (!items.contains(item)) {
throw new IllegalArgumentException();
}
Rectangle bounds = new Rectangle(LEFT, TOP, 0, 0);
for (StripItem eachItem : items) {
Point eachSize = computeSize(eachItem);
if (eachItem.equals(item)) {
bounds.width = eachSize.x;
break;
}
bounds.x += eachSize.x + SPACE;
}
for (StripItem eachItem : items) {
Point eachSize = computeSize(eachItem);
bounds.height = Math.max(bounds.height, eachSize.y);
}
return bounds;
}
private Rectangle computeImageBounds(StripItem item, Rectangle bounds) {
if (item == null || bounds == null) {
throw new NullPointerException();
}
if (!items.contains(item)) {
throw new IllegalArgumentException();
}
Rectangle imageBounds = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
imageBounds.x += ITEM_LEFT;
imageBounds.y += imageBounds.height / 2;
imageBounds.width = 0;
imageBounds.height = 0;
if (item.hasImage()) {
Point imageSize = item.getImageSize();
imageBounds.y -= imageSize.y / 2;
imageBounds.width = imageSize.x;
imageBounds.height = imageSize.y;
}
return imageBounds;
}
private Rectangle computeTextBounds(StripItem item, Rectangle bounds) {
if (item == null || bounds == null) {
throw new NullPointerException();
}
if (!items.contains(item)) {
throw new IllegalArgumentException();
}
Rectangle textBounds = computeImageBounds(item, bounds);
textBounds.x += textBounds.width;
textBounds.y += textBounds.height / 2;
textBounds.width = 0;
textBounds.height = 0;
if (item.hasText()) {
if (item.hasImage()) {
textBounds.x += TEXT_INDENT;
}
Point textSize = item.getTextSize();
textBounds.y -= textSize.y / 2;
textBounds.width = textSize.x;
textBounds.height = textSize.y;
}
return textBounds;
}
private Rectangle computeCloseButtonBounds(StripItem item, Rectangle bounds) {
if (item == null || bounds == null) {
throw new NullPointerException();
}
if (!items.contains(item)) {
throw new IllegalArgumentException();
}
Point closeButtonSize = getCloseButtonSize();
Rectangle closeButtonBounds = computeTextBounds(item, bounds);
closeButtonBounds.x += closeButtonBounds.width;
closeButtonBounds.y += closeButtonBounds.height / 2 - closeButtonSize.y / 2;
closeButtonBounds.width = closeButtonSize.x;
closeButtonBounds.height = closeButtonSize.y;
if (item.hasImage() || item.hasText()) {
closeButtonBounds.x += CLOSE_INDENT;
}
return closeButtonBounds;
}
private Point getCloseButtonSize() {
Image closeButtonImage = getCloseButtonImage(false);
Rectangle closeButtonImageBounds = closeButtonImage.getBounds();
return new Point(closeButtonImageBounds.width, closeButtonImageBounds.height);
}
private Image getCloseButtonImage(boolean highlight) {
if (highlight) {
return UIImageResource.T.closeHighlight10();
}
return UIImageResource.T.closeNormal10();
}
private StripItem[] getItemsInPaintOrder() {
List<StripItem> itemsInPaintOrder = new ArrayList<StripItem>();
for (StripItem item : items) {
if (item.isBoundsAnimating()) {
continue;
}
int state = item.getState();
if ((state & StripItem.DRAGGED) == StripItem.DRAGGED) {
continue;
}
itemsInPaintOrder.add(item);
}
for (StripItem item : items) {
if (item.isBoundsAnimating()) {
itemsInPaintOrder.add(item);
}
}
for (StripItem item : getItems(StripItem.DRAGGED, false)) {
itemsInPaintOrder.add(item);
}
return itemsInPaintOrder.toArray(new StripItem[itemsInPaintOrder.size()]);
}
private StripItem[] getAffectedItemsAnimated(StripItem drag, int delta) {
List<StripItem> affected = new ArrayList<StripItem>();
Rectangle dragBounds = drag.getBounds();
for (StripItem item : items) {
if (item.equals(drag)) {
continue;
}
Rectangle bounds = item.getBounds();
if (delta > 0) {
if (dragBounds.x <= bounds.x + bounds.width / 2 && dragBounds.x + dragBounds.width + delta >= bounds.x + bounds.width / 2) {
affected.add(item);
}
} else {
if (dragBounds.x + dragBounds.width >= bounds.x + bounds.width / 2 && dragBounds.x + delta <= bounds.x + bounds.width / 2) {
affected.add(item);
}
}
}
return affected.toArray(new StripItem[affected.size()]);
}
private StripItem[] getAffectedItemsNonAnimated(StripItem drag, StripItem on) {
List<StripItem> affected = new ArrayList<StripItem>();
if (!drag.equals(on)) {
StripItem min;
StripItem max;
if (drag.getBounds().x < on.getBounds().x) {
min = drag;
max = on;
} else {
min = on;
max = drag;
}
for (StripItem item : items) {
if (item.getBounds().x >= min.getBounds().x && item.getBounds().x <= max.getBounds().x + max.getBounds().width) {
affected.add(item);
}
}
}
affected.remove(drag);
return affected.toArray(new StripItem[affected.size()]);
}
private void reorderItems() {
Collections.sort(items, comp);
}
private boolean isBoundsAnimating() {
for (StripItem item : items) {
if (item.isBoundsAnimating()) {
return true;
}
}
return false;
}
private StripItem[] getItemsBehindOutwards(Rectangle dragBounds) {
List<StripItem> itemsBehind = new ArrayList<StripItem>();
for (StripItem item : items) {
int state = item.getState();
if ((state & StripItem.DRAGGED) == StripItem.DRAGGED) {
continue;
}
Rectangle bounds = item.getBounds();
if (bounds.x > dragBounds.x) {
itemsBehind.add(item);
}
}
return itemsBehind.toArray(new StripItem[itemsBehind.size()]);
}
private StripItem[] getItemsBehindInwards(Rectangle dragBounds) {
List<StripItem> itemsBehind = new ArrayList<StripItem>();
for (StripItem item : items) {
int state = item.getState();
if ((state & StripItem.DRAGGED) == StripItem.DRAGGED) {
continue;
}
Rectangle bounds = item.getBounds();
if (bounds.x + bounds.width > dragBounds.x) {
itemsBehind.add(item);
}
}
return itemsBehind.toArray(new StripItem[itemsBehind.size()]);
}
public static void main(String[] args) {
Display display = Display.getDefault();
Shell shell = new Shell(display);
StripBar bar = new StripBar(shell, SWT.DOUBLE_BUFFERED | SWT.BORDER);
Animator.setDefaultTimingSource(new SWTTimingSource(16, TimeUnit.MILLISECONDS, display));
Animator.getDefaultTimingSource().init();
GridLayout layout = new GridLayout();
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
layout.marginWidth = 0;
layout.marginHeight = 0;
shell.setLayout(layout);
GridData layoutData = new GridData();
layoutData.horizontalAlignment = SWT.FILL;
layoutData.verticalAlignment = SWT.FILL;
layoutData.grabExcessHorizontalSpace = true;
bar.setLayoutData(layoutData);
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.setAnimate(true);
bar.pack();
bar.layout();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}