package org.xmind.ui.viewers;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.layout.RowDataFactory;
import org.eclipse.jface.layout.RowLayoutFactory;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IElementComparer;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
public class ImageListViewer extends StructuredViewer {
protected static class ImageItem {
private ImageListViewer listViewer;
private Object data;
private Composite bar;
private Label imageLabel;
public ImageItem(ImageListViewer listViewer, Composite parent) {
this.listViewer = listViewer;
bar = new Composite(parent, SWT.NONE);
bar.setBackground(parent.getBackground());
bar.setData(this);
RowLayoutFactory.fillDefaults().wrap(true)
.extendedMargins(5, 5, 1, 1).applyTo(bar);
imageLabel = new Label(bar, SWT.NONE);
imageLabel.setImage(null);
imageLabel.setBackground(bar.getBackground());
RowDataFactory.swtDefaults().hint(SWT.DEFAULT, 80)
.applyTo(imageLabel);
addControlListeners();
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public ImageListViewer getListViewer() {
return listViewer;
}
public Control getControl() {
return bar;
}
protected Composite getBarComposite() {
return bar;
}
public Image getImage() {
return imageLabel.getImage();
}
public void setImage(Image image) {
imageLabel.setImage(image);
}
private void addControlListeners() {
Listener listener = new Listener() {
public void handleEvent(Event event) {
int type = event.type;
switch (type) {
case SWT.MouseExit:
userExit(event);
break;
case SWT.MouseDoubleClick:
if (OpenStrategy.getOpenMethod() == OpenStrategy.DOUBLE_CLICK) {
userOpen(event);
}
break;
case SWT.MouseMove:
userSelect(event);
break;
case SWT.MouseDown:
userSelect(event);
break;
}
}
};
bar.addListener(SWT.MouseDoubleClick, listener);
bar.addListener(SWT.MouseMove, listener);
bar.addListener(SWT.MouseExit, listener);
bar.addListener(SWT.MouseDown, listener);
imageLabel.addListener(SWT.MouseDoubleClick, listener);
imageLabel.addListener(SWT.MouseMove, listener);
imageLabel.addListener(SWT.MouseExit, listener);
imageLabel.addListener(SWT.MouseDown, listener);
}
protected void userOpen(Event e) {
getListViewer().reveal(data);
}
protected void userSelect(Event e) {
bar.redraw();
bar.setBackground(getSelectionBackground());
imageLabel.setBackground(getSelectionBackground());
}
protected void userExit(Event event) {
bar.redraw();
Color background = bar.getParent().getBackground();
bar.setBackground(background);
imageLabel.setBackground(background);
}
public void dispose() {
bar.dispose();
}
public boolean isDisposed() {
return bar.isDisposed();
}
}
private static Color selectionBackground = null;
protected static Color getSelectionBackground() {
if (selectionBackground == null) {
selectionBackground = Display.getCurrent().getSystemColor(
SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT);
}
return selectionBackground;
}
private Composite list;
private List<Object> listMap = new ArrayList<Object>();
private List<ImageItem> items = new ArrayList<ImageItem>();
public ImageListViewer(final Composite parent, int style) {
list = new Composite(parent, style) {
@Override
public boolean setFocus() {
return super.setFocus();
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
Point size;
if (getItemCount() == 0) {
size = new Point(0, 0);
if (wHint != SWT.DEFAULT)
size.x = wHint;
if (hHint != SWT.DEFAULT)
size.y = hHint;
Rectangle trim = computeTrim(0, 0, size.x, size.y);
size = new Point(trim.width, trim.height);
} else {
size = super.computeSize(parent.getBounds().width,
SWT.DEFAULT, true);
}
return size;
}
};
list.setTabList(new Control[0]);
list.setBackground(parent.getBackground());
RowLayoutFactory.fillDefaults().spacing(0).wrap(true).applyTo(list);
list.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
handleDispose(e);
}
});
}
public int getItemCount() {
return listGetItemCount();
}
protected int listGetItemCount() {
return items.size();
}
protected ImageItem listAdd(Image image, Object data, int index) {
ImageItem newItem = new ImageItem(this, list);
RowDataFactory.swtDefaults().hint(SWT.DEFAULT, 80)
.applyTo(newItem.getControl());
newItem.setImage(image);
newItem.setData(data);
list.layout();
if (index < 0 || index >= listGetItemCount()) {
items.add(newItem);
} else {
ImageItem oldItem = items.get(index);
items.add(index, newItem);
newItem.getControl().moveAbove(oldItem.getControl());
}
return newItem;
}
protected ImageItem listRemove(int index) {
if (index < 0 || index >= listGetItemCount())
return null;
ImageItem item = items.remove(index);
if (item != null)
item.dispose();
return item;
}
protected void listRemoveAll() {
for (ImageItem item : items)
item.dispose();
items.clear();
}
protected void listSetItem(Image image, Object data, int index) {
if (index < 0 || index >= listGetItemCount())
return;
ImageItem item = items.get(index);
if (!item.isDisposed()) {
item.setImage(image);
item.setData(data);
}
}
protected int getElementIndex(Object element) {
IElementComparer comparer = getComparer();
if (comparer == null) {
return listMap.indexOf(element);
}
int size = listMap.size();
for (int i = 0; i < size; i++) {
if (comparer.equals(element, listMap.get(i)))
return i;
}
return -1;
}
public Object getElementAt(int index) {
if (index >= 0 && index < listMap.size())
return listMap.get(index);
return null;
}
public int indexForElement(Object element) {
ViewerComparator comparator = getComparator();
if (comparator == null) {
return listGetItemCount();
}
int count = listGetItemCount();
int min = 0, max = count - 1;
while (min <= max) {
int mid = (min + max) / 2;
Object data = listMap.get(mid);
int compare = comparator.compare(this, data, element);
if (compare == 0) {
// find first item > element
while (compare == 0) {
++mid;
if (mid >= count) {
break;
}
data = listMap.get(mid);
compare = comparator.compare(this, data, element);
}
return mid;
}
if (compare < 0) {
min = mid + 1;
} else {
max = mid - 1;
}
}
return min;
}
public void inputChanged(Object input, Object oldInput) {
listMap.clear();
Object[] children = getSortedChildren(getRoot());
int size = children.length;
listRemoveAll();
for (int i = 0; i < size; i++) {
Object el = children[i];
Image image = getImage((ILabelProvider) getLabelProvider(), el);
ImageItem item = listAdd(image, el, -1);
listMap.add(el);
mapElement(el, item.getControl());
}
}
public IBaseLabelProvider getLabelProvider() {
return super.getLabelProvider();
}
@Override
public void setLabelProvider(IBaseLabelProvider labelProvider) {
Assert.isTrue(labelProvider instanceof ILabelProvider);
super.setLabelProvider(labelProvider);
}
public void remove(Object element) {
remove(new Object[] { element });
}
public void remove(final Object[] elements) {
assertElementsNotNull(elements);
if (elements.length == 0)
return;
preservingSelection(new Runnable() {
public void run() {
internalRemove(elements);
}
});
}
private void internalRemove(final Object[] elements) {
Object input = getInput();
for (int i = 0; i < elements.length; ++i) {
if (equals(elements[i], input)) {
setInput(null);
return;
}
int ix = getElementIndex(elements[i]);
if (ix >= 0) {
ImageItem item = listRemove(ix);
listMap.remove(ix);
unmapElement(elements[i], item.getControl());
}
}
}
@Override
protected Widget doFindInputItem(Object element) {
if (element != null && equals(element, getRoot())) {
return getControl();
}
return null;
}
@Override
protected Widget doFindItem(Object element) {
if (element != null) {
int index = getElementIndex(element);
if (index >= 0) {
return items.get(index).getControl();
}
}
return null;
}
@Override
protected void doUpdateItem(Widget item, Object element, boolean fullMap) {
if (element != null) {
int ix = getElementIndex(element);
if (ix >= 0) {
ILabelProvider labelProvider = (ILabelProvider) getLabelProvider();
Image image = getImage(labelProvider, element);
listSetItem(image, element, ix);
}
}
}
@Override
protected List getSelectionFromWidget() {
List<Object> list = new ArrayList<Object>();
return list;
}
@Override
protected void internalRefresh(Object element) {
Control list = getControl();
if (element == null || equals(element, getRoot())) {
if (listMap != null) {
listMap.clear();
}
unmapAllElements();
List selection = getSelectionFromWidget();
int topIndex = -1;
if (selection == null || selection.isEmpty()) {
topIndex = listGetTopIndex();
}
list.setRedraw(false);
listRemoveAll();
Object[] children = getSortedChildren(getRoot());
ILabelProvider labelProvider = (ILabelProvider) getLabelProvider();
for (int i = 0; i < children.length; i++) {
Object el = children[i];
Image image = getImage(labelProvider, el);
ImageItem item = listAdd(image, el, -1);
listMap.add(el);
mapElement(el, item.getControl());
}
list.setRedraw(true);
if (topIndex == -1) {
setSelectionToWidget(selection, false);
}
} else {
doUpdateItem(list, element, true);
}
}
@Override
public void reveal(Object element) {
if (element == null)
return;
IEditorPart activeEditor = null;
IWorkbenchWindow window = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow();
if (window != null) {
IWorkbenchPage page = window.getActivePage();
if (page != null)
activeEditor = page.getActiveEditor();
}
if (activeEditor == null)
return;
activeEditor.getSite().getPage().activate(activeEditor);
ISelectionProvider selectionProvider = activeEditor.getSite()
.getSelectionProvider();
if (selectionProvider != null)
selectionProvider.setSelection(new StructuredSelection(element));
}
@Override
protected void setSelectionToWidget(List in, boolean reveal) {
if (in != null && in.size() != 0) { // clear selection
int n = in.size();
int[] ixs = new int[n];
int count = 0;
for (int i = 0; i < n; ++i) {
Object el = in.get(i);
int ix = getElementIndex(el);
if (ix >= 0) {
ixs[count++] = ix;
}
}
if (count < n) {
System.arraycopy(ixs, 0, ixs = new int[count], 0, count);
}
}
}
@Override
public Control getControl() {
return list;
}
public Composite getListComposite() {
return list;
}
protected int listGetTopIndex() {
return -1;
}
private Image getImage(ILabelProvider labelProvider, Object element) {
Image image = labelProvider.getImage(element);
ImageData imageData = image.getImageData();
if (imageData.height > 80) {
return new Image(null, imageData.scaledTo(imageData.width * 80
/ imageData.height, 80));
}
return image;
}
}