/*******************************************************************************
 * Copyright (c) 2011, 2016 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.custom;


import org.eclipse.swt.*;
import org.eclipse.swt.accessibility.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;

/**
 * A TreeCursor provides a way for the user to navigate around a Tree with columns using the
 * keyboard. It also provides a mechanism for selecting an individual cell in a tree.
 * <p>
 * For a detailed example of using a TreeCursor to navigate to a cell and then edit it see
 * http://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet360.java .
 *
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>BORDER</dd>
 * <dt><b>Events:</b></dt>
 * <dd>Selection, DefaultSelection</dd>
 * </dl>
 *
 * @since 3.8
 */
public class TreeCursor extends Canvas {
	Tree tree;
	TreeItem row;
	TreeColumn column;
	Listener listener, treeListener, resizeListener, disposeItemListener, disposeColumnListener;

	Color background = null;
	Color foreground = null;

	/* By default, invert the list selection colors */
	static final int BACKGROUND = SWT.COLOR_LIST_SELECTION_TEXT;
	static final int FOREGROUND = SWT.COLOR_LIST_SELECTION;

/**
 * Constructs a new instance of this class given its parent tree and a style value describing
 * its behavior and appearance.
 * <p>
 * The style value is either one of the style constants defined in class <code>SWT</code> which
 * is applicable to instances of this class, or must be built by <em>bitwise OR</em>'ing
 * together (that is, using the <code>int</code> "|" operator) two or more of those
 * <code>SWT</code> style constants. The class description lists the style constants that are
 * applicable to the class. Style bits are also inherited from superclasses.
 * </p>
 *
 * @param parent a Tree control which will be the parent of the new instance (cannot be null)
 * @param style the style of control to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see SWT#BORDER
 * @see Widget#checkSubclass()
 * @see Widget#getStyle()
 */
public TreeCursor(Tree parent, int style) {
	super(parent, style);
	tree = parent;
	setBackground(null);
	setForeground(null);

	listener = event -> {
		if (row != null) {
			/*
			 * Detect cases where the cursor position has become invalid and fix it.
			 * The typical cause of this is programmatic tree changes, such as
			 * expanding/collapsing and item and creating/disposing items.
			 */
			if (row.isDisposed()) {
				unhookRowColumnListeners();
				_resize();
				tree.setFocus();
				return;
			}
			TreeItem current = row;
			TreeItem parentItem = row.getParentItem();
			while (parentItem != null && !parentItem.getExpanded()) {
				current = parentItem;
				parentItem = current.getParentItem();
			}
			if (current != row) {
				setRowColumn(current, column, false);
			}
		}
		switch (event.type) {
			case SWT.Dispose:
				onDispose(event);
				break;
			case SWT.FocusIn:
			case SWT.FocusOut:
				redraw();
				break;
			case SWT.KeyDown:
				keyDown(event);
				break;
			case SWT.Paint:
				paint(event);
				break;
			case SWT.Traverse:
				event.doit = true;
				switch (event.detail) {
					case SWT.TRAVERSE_ARROW_NEXT:
					case SWT.TRAVERSE_ARROW_PREVIOUS:
					case SWT.TRAVERSE_RETURN:
						event.doit = false;
						break;
				}
				break;
		}
	};
	int[] events = new int[] { SWT.Dispose, SWT.FocusIn, SWT.FocusOut, SWT.KeyDown, SWT.Paint, SWT.Traverse };
	for (int i = 0; i < events.length; i++) {
		addListener(events[i], listener);
	}

	treeListener = event -> {
		switch (event.type) {
			case SWT.Collapse:
				treeCollapse(event);
				break;
			case SWT.Expand:
				treeExpand(event);
				break;
			case SWT.FocusIn:
				treeFocusIn(event);
				break;
			case SWT.MouseDown:
				treeMouseDown(event);
				break;
		}
	};
	tree.addListener(SWT.Collapse, treeListener);
	tree.addListener(SWT.Expand, treeListener);
	tree.addListener(SWT.FocusIn, treeListener);
	tree.addListener(SWT.MouseDown, treeListener);

	disposeItemListener = event -> {
		TreeItem currentItem = row;
		while (currentItem != null) {
			currentItem.removeListener(SWT.Dispose, disposeItemListener);
			currentItem = currentItem.getParentItem();
		}
		TreeItem disposedItem = (TreeItem)event.widget;
		TreeItem parentItem = disposedItem.getParentItem();
		if (parentItem != null) {
			setRowColumn(parentItem, column, true);
		} else {
			if (tree.getItemCount() == 1) {
				unhookRowColumnListeners();
			} else {
				TreeItem newFocus = null;
				int rowIndex = tree.indexOf(disposedItem);
				if (rowIndex != 0) {
					TreeItem previousItem = tree.getItem(rowIndex - 1);
					if (!previousItem.isDisposed()) {
						newFocus = previousItem;
					}
				}
				if (newFocus == null && rowIndex + 1 < tree.getItemCount()) {
					TreeItem nextItem = tree.getItem(rowIndex + 1);
					if (!nextItem.isDisposed()) {
						newFocus = nextItem;
					}
				}
				if (newFocus != null) {
					setRowColumn(newFocus, column, true);
				} else {
					unhookRowColumnListeners();
				}
			}
		}
		_resize();
	};
	disposeColumnListener = event -> {
		if (column != null) {
			if (tree.getColumnCount() == 1) {
				column = null;
			} else {
				int columnIndex = tree.indexOf(column);
				int positionIndex = columnIndex;
				int[] columnOrder = tree.getColumnOrder();
				for (int i = 0; i < columnOrder.length; i++) {
					if (columnOrder[i] == columnIndex) {
						positionIndex = i;
						break;
					}
				}
				if (positionIndex == columnOrder.length - 1) {
					setRowColumn(row, tree.getColumn(columnOrder[positionIndex - 1]), true);
				} else {
					setRowColumn(row, tree.getColumn(columnOrder[positionIndex + 1]), true);
				}
			}
		}
		_resize();
	};
	resizeListener = event -> _resize();
	ScrollBar hBar = tree.getHorizontalBar();
	if (hBar != null) {
		hBar.addListener(SWT.Selection, resizeListener);
	}
	ScrollBar vBar = tree.getVerticalBar();
	if (vBar != null) {
		vBar.addListener(SWT.Selection, resizeListener);
	}

	getAccessible().addAccessibleControlListener(new AccessibleControlAdapter() {
		@Override
		public void getRole(AccessibleControlEvent e) {
			e.detail = ACC.ROLE_TABLECELL;
		}
	});
	getAccessible().addAccessibleListener(new AccessibleAdapter() {
		@Override
		public void getName(AccessibleEvent e) {
			if (row == null) return;
			int columnIndex = column == null ? 0 : tree.indexOf(column);
			e.result = row.getText(columnIndex);
		}
	});
}

/**
 * Adds the listener to the collection of listeners who will be notified when the receiver's
 * selection changes, by sending it one of the messages defined in the
 * <code>SelectionListener</code> interface.
 * <p>
 * When <code>widgetSelected</code> is called, the item field of the event object is valid. If
 * the receiver has <code>SWT.CHECK</code> style set and the check selection changes, the event
 * object detail field contains the value <code>SWT.CHECK</code>.
 * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
 * </p>
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see SelectionListener
 * @see SelectionEvent
 * @see #removeSelectionListener(SelectionListener)
 */
public void addSelectionListener(SelectionListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener(listener);
	addListener(SWT.Selection, typedListener);
	addListener(SWT.DefaultSelection, typedListener);
}

int countSubTreePages(TreeItem root) {
	int pages = 1;
	if (root == null) return 0;
	if (root.getItemCount() == 0) return 1;
	if (!root.getExpanded()) return 1;
	TreeItem[] items = root.getItems();
	for (int i = 0; i < items.length; i++) {
		pages += countSubTreePages(items[i]);
	}
	return pages;
}

int findIndex(TreeItem[] items, TreeItem treeItem) {
	if (items == null || treeItem == null) return -1;
	Rectangle rect = treeItem.getBounds();
	int index = 0;
	for (int i = 0; i < items.length; i++) {
		TreeItem previousItem = null;
		TreeItem currentItem = items[i];
		if (i > 0) previousItem = items[i - 1];
		Rectangle rect1 = currentItem.getBounds();
		if (rect.y == rect1.y) return index;
		if (rect.y < rect1.y) {
			return index - 1 + findIndex(previousItem.getItems(), treeItem);
		}
		if (rect.y > rect1.y && i == items.length - 1) {
			return index + findIndex(currentItem.getItems(), treeItem);
		}
		if (rect.y >= rect1.y + (1 + currentItem.getItemCount()) * tree.getItemHeight() && currentItem.getExpanded()) {
			index += countSubTreePages(currentItem);
			continue;
		}
		index++;
	}
	return -1;
}

TreeItem findItem(TreeItem[] items, Point pt) {
	int start = 0, end = items.length - 1;
	int index = end / 2;
	while (end - start > 1) {
		TreeItem currentItem = items[index];
		Rectangle bounds = currentItem.getBounds();
		if (pt.y < bounds.y) {
			end = index;
			index = (end - start) / 2;
		} else {
			start = index;
			index = start + ((end - start) / 2);
		}
	}

	Rectangle endBounds = items[end].getBounds();
	if (endBounds.y < pt.y) {
		if (endBounds.y + endBounds.height < pt.y) {
			if (!items[end].getExpanded()) return null;
			return findItem(items[end].getItems(), pt);
		}
		int[] columnOrder = tree.getColumnOrder();
		Rectangle bounds = null;
		if (columnOrder.length > 0) {
			Rectangle rect1 = items[end].getBounds(columnOrder[0]);
			Rectangle rect2 = items[end].getBounds(columnOrder[columnOrder.length - 1]);
			bounds = rect1.union(rect2);
			bounds.height += tree.getLinesVisible() ? tree.getGridLineWidth() : 0;
		} else {
			bounds = items[end].getBounds();
		}
		return bounds.contains(pt) ? items[end] : null;
	}

	Rectangle startBounds = items[start].getBounds();
	if (startBounds.y + startBounds.height < pt.y) {
		return findItem(items[start].getItems(), pt);
	}
	int[] columnOrder = tree.getColumnOrder();
	Rectangle bounds = null;
	if (columnOrder.length > 0) {
		Rectangle rect1 = items[start].getBounds(columnOrder[0]);
		Rectangle rect2 = items[start].getBounds(columnOrder[columnOrder.length - 1]);
		bounds = rect1.union(rect2);
		bounds.height += tree.getLinesVisible() ? tree.getGridLineWidth() : 0;
	} else {
		bounds = items[start].getBounds();
	}
	return bounds.contains(pt) ? items[start] : null;
}

/**
 * Returns the background color that the receiver will use to draw.
 *
 * @return the receiver's background color
 */
@Override
public Color getBackground() {
	checkWidget();
	if (background == null) {
		return getDisplay().getSystemColor(BACKGROUND);
	}
	return background;
}

/**
 * Returns the index of the column over which the TreeCursor is positioned.
 *
 * @return the column index for the current position
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getColumn() {
	checkWidget();
	return column == null ? 0 : tree.indexOf(column);
}

/**
 * Returns the foreground color that the receiver will use to draw.
 *
 * @return the receiver's foreground color
 */
@Override
public Color getForeground() {
	checkWidget();
	if (foreground == null) {
		return getDisplay().getSystemColor(FOREGROUND);
	}
	return foreground;
}

TreeItem getLastVisibleItem(TreeItem[] items) {
	if (items == null) return null;
	TreeItem last = items[items.length - 1];
	if (last.getExpanded() && last.getItemCount() > 0) {
		return getLastVisibleItem(last.getItems());
	}
	return last;
}

TreeItem getNextItem(TreeItem item) {
	if (item == null) return null;
	if (item.getExpanded() && item.getItemCount() > 0) {
		return item.getItem(0);
	}

	TreeItem parentItem = item.getParentItem();
	while (parentItem != null) {
		int index = parentItem.indexOf(item);
		if (index == -1) return null;
		if (index < parentItem.getItemCount() - 1) {
			return parentItem.getItem(index + 1);
		}
		item = parentItem;
		parentItem = item.getParentItem();
	}
	int index = tree.indexOf(item);
	if (index == -1) return null;
	if (index == tree.getItemCount() - 1) return null;
	return tree.getItem(index + 1);
}

TreeItem getPreviousItem(TreeItem item) {
	if (item == null) return null;
	TreeItem parentItem = item.getParentItem();
	if (parentItem == null) {
		int index = tree.indexOf(item);
		if (index == -1 || index == 0) return null;
		item = tree.getItem(index - 1);
		if (item.getExpanded() && item.getItemCount() > 0) {
			return getLastVisibleItem(item.getItems());
		}
		return item;
	}
	int index = parentItem.indexOf(item);
	if (index == -1) return null;
	if (index == 0) return parentItem;
	item = parentItem.getItem(index - 1);
	if (item.getExpanded() && item.getItemCount() > 0) {
		return getLastVisibleItem(item.getItems());
	}
	return item;
}

/**
 * Returns the row over which the TreeCursor is positioned.
 *
 * @return the item for the current position, or <code>null</code> if none
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public TreeItem getRow() {
	checkWidget();
	return row;
}

void keyDown(Event event) {
	if (row == null) return;
	switch (event.character) {
		case SWT.CR:
			notifyListeners(SWT.DefaultSelection, new Event());
			return;
	}
	switch (event.keyCode) {
		case SWT.ARROW_UP:
			TreeItem previousItem = getPreviousItem(row);
			if (previousItem != null) {
				setRowColumn(previousItem, column, true);
			}
			break;
		case SWT.ARROW_DOWN:
			TreeItem nextItem = getNextItem(row);
			if (nextItem != null) {
				setRowColumn(nextItem, column, true);
			}
			break;
		case SWT.ARROW_LEFT:
		case SWT.ARROW_RIGHT: {
			if ((event.stateMask & SWT.MOD1) != 0) {
				row.setExpanded (event.keyCode == SWT.ARROW_RIGHT);
				break;
			}
			int columnCount = tree.getColumnCount();
			if (columnCount == 0) break;
			int columnIndex = column == null ? 0 : tree.indexOf(column);
			int[] columnOrder = tree.getColumnOrder();
			int index = 0;
			while (index < columnOrder.length) {
				if (columnOrder[index] == columnIndex) break;
				index++;
			}
			if (index == columnOrder.length) index = 0;
			int leadKey = (getStyle() & SWT.RIGHT_TO_LEFT) != 0 ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
			TreeItem parentRow = row.getParentItem();
			int rowIndex = tree.indexOf(row);
			if (event.keyCode == leadKey) {
				if (parentRow != null) {
					setRowColumn(row, tree.getColumn(columnOrder[Math.max(0, index - 1)]), true);
				} else {
					setRowColumn(rowIndex, columnOrder[Math.max(0, index - 1)], true);
				}
			} else {
				if (parentRow != null) {
					setRowColumn(row, tree.getColumn(columnOrder[Math.min(columnCount - 1, index + 1)]), true);
				} else {
					setRowColumn(rowIndex, columnOrder[Math.min(columnCount - 1, index + 1)], true);
				}
			}
			break;
		}
		case SWT.HOME:
			int columnIndex = column == null ? 0 : tree.indexOf(column);
			setRowColumn(0, columnIndex, true);
			break;
		case SWT.END: {
			TreeItem[] items = tree.getItems();
			setRowColumn(getLastVisibleItem(items), column, true);
			break;
		}
		case SWT.PAGE_UP: {
			Rectangle rect = tree.getClientArea();
			Rectangle itemRect = tree.getTopItem().getBounds();
			TreeItem item = row;
			int index = findIndex(tree.getItems(), item);
			int itemHeight = tree.getItemHeight();
			rect.height -= itemRect.y;
			int page = Math.max(1, rect.height / itemHeight);
			if (index - page <= 0) {
				TreeItem first = tree.getItem(0);
				setRowColumn(first, column, true);
				break;
			}
			for (int i = 0; i < page; i++) {
				item = getPreviousItem(item);
			}
			setRowColumn(item, column, true);
			break;
		}
		case SWT.PAGE_DOWN: {
			Rectangle rect = tree.getClientArea();
			Rectangle itemRect = tree.getTopItem().getBounds();
			TreeItem item = row;
			int index = findIndex(tree.getItems(), item);
			int height = tree.getItemHeight();
			rect.height -= itemRect.y;
			TreeItem last = getLastVisibleItem(tree.getItems());
			int page = Math.max(1, rect.height / height);
			int end = findIndex(tree.getItems(), last);
			if (end <= index + page) {
				setRowColumn(last, column, true);
				break;
			}
			for (int i = 0; i < page; i++) {
				item = getNextItem(item);
			}
			setRowColumn(item, column, true);
			break;
		}
	}
}

void onDispose(Event event) {
	removeListener(SWT.Dispose, listener);
	notifyListeners(SWT.Dispose, event);
	event.type = SWT.None;

	tree.removeListener(SWT.Collapse, treeListener);
	tree.removeListener(SWT.Expand, treeListener);
	tree.removeListener(SWT.FocusIn, treeListener);
	tree.removeListener(SWT.MouseDown, treeListener);
	unhookRowColumnListeners();
	ScrollBar hBar = tree.getHorizontalBar();
	if (hBar != null) {
		hBar.removeListener(SWT.Selection, resizeListener);
	}
	ScrollBar vBar = tree.getVerticalBar();
	if (vBar != null) {
		vBar.removeListener(SWT.Selection, resizeListener);
	}
}

void paint(Event event) {
	if (row == null) return;
	int columnIndex = column == null ? 0 : tree.indexOf(column);
	int orderedIndex = columnIndex;
	int[] columnOrder = tree.getColumnOrder();
	for (int i = 0; i < columnOrder.length; i++) {
		if (columnOrder[i] == columnIndex) {
			orderedIndex = i;
			break;
		}
	}
	GC gc = event.gc;
	gc.setBackground(getBackground());
	gc.setForeground(getForeground());
	gc.fillRectangle(event.x, event.y, event.width, event.height);
	Image image = row.getImage(columnIndex);
	int x = 0;
	// Temporary code - need a better way to determine trim
	String platform = SWT.getPlatform();
	if (image != null) {
		if ("win32".equals(platform)) { //$NON-NLS-1$
			if (orderedIndex > 0) {
				x += 2;
			}
		} else {
			x += 2;
		}
	}
	Point size = getSize();
	if (image != null) {
		Rectangle imageSize = image.getBounds();
		int imageY = (size.y - imageSize.height) / 2;
		gc.drawImage(image, x, imageY);
		x += imageSize.width;
	}
	String text = row.getText(columnIndex);
	if (text.length() > 0) {
		Rectangle bounds = row.getBounds(columnIndex);
		Point extent = gc.stringExtent(text);
		// Temporary code - need a better way to determine trim
		if ("win32".equals(platform)) { //$NON-NLS-1$
			if (tree.getColumnCount() == 0 || orderedIndex == 0) {
				x += image == null ? 2 : 5;
			} else {
				int alignmnent = column.getAlignment();
				switch (alignmnent) {
					case SWT.LEFT:
						x += image == null ? 5 : 3;
						break;
					case SWT.RIGHT:
						x = bounds.width - extent.x - 2;
						break;
					case SWT.CENTER:
						x += Math.ceil((bounds.width - x - extent.x) / 2.0);
						break;
				}
			}
		} else {
			if (tree.getColumnCount() == 0) {
				x += image == null ? 4 : 3;
			} else {
				int alignmnent = column.getAlignment();
				switch (alignmnent) {
					case SWT.LEFT:
						x += image == null ? 5 : 3;
						break;
					case SWT.RIGHT:
						x = bounds.width - extent.x - 2;
						break;
					case SWT.CENTER:
						x += (bounds.width - x - extent.x) / 2 + 2;
						break;
				}
			}
		}
		int textY = (size.y - extent.y) / 2;
		gc.drawString(text, x, textY);
	}
	if (isFocusControl()) {
		Display display = getDisplay();
		gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
		gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
		gc.drawFocus(0, 0, size.x, size.y);
	}
}

/**
 * Removes the listener from the collection of listeners who will be notified when the
 * receiver's selection changes.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see SelectionListener
 * @see #addSelectionListener(SelectionListener)
 */
public void removeSelectionListener(SelectionListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	removeListener(SWT.Selection, listener);
	removeListener(SWT.DefaultSelection, listener);
}

void _resize() {
	if (row == null) {
		setBounds(-200, -200, 0, 0);
	} else {
		int columnIndex = column == null ? 0 : tree.indexOf(column);
		setBounds(row.getBounds(columnIndex));
	}
}

/**
 * Sets the receiver's background color to the color specified
 * by the argument, or to the default system color for the control
 * if the argument is null.
 * <p>
 * Note: This operation is a hint and may be overridden by the platform.
 * For example, on Windows the background of a Button cannot be changed.
 * </p>
 * @param color the new color (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
@Override
public void setBackground (Color color) {
	background = color;
	super.setBackground(getBackground());
	redraw();
}
/**
 * Sets the receiver's foreground color to the color specified
 * by the argument, or to the default system color for the control
 * if the argument is null.
 * <p>
 * Note: This operation is a hint and may be overridden by the platform.
 * </p>
 * @param color the new color (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
@Override
public void setForeground (Color color) {
	foreground = color;
	super.setForeground(getForeground());
	redraw();
}

void setRowColumn(int row, int column, boolean notify) {
	TreeItem item = row == -1 ? null : tree.getItem(row);
	TreeColumn col = column == -1 || tree.getColumnCount() == 0 ? null : tree.getColumn(column);
	setRowColumn(item, col, notify);
}

void setRowColumn(TreeItem row, TreeColumn column, boolean notify) {
	if (this.row != null && this.row != row) {
		TreeItem currentItem = this.row;
		while (currentItem != null) {
			currentItem.removeListener(SWT.Dispose, disposeItemListener);
			currentItem = currentItem.getParentItem();
		}
		this.row = null;
	}
	if (this.column != null && this.column != column) {
		this.column.removeListener(SWT.Dispose, disposeColumnListener);
		this.column.removeListener(SWT.Move, resizeListener);
		this.column.removeListener(SWT.Resize, resizeListener);
		this.column = null;
	}
	if (row != null) {
		if (this.row != row) {
			this.row = row;
			TreeItem currentItem = row;
			while (currentItem != null) {
				currentItem.addListener(SWT.Dispose, disposeItemListener);
				currentItem = currentItem.getParentItem();
			}
			tree.showItem(row);
		}
		if (this.column != column && column != null) {
			this.column = column;
			column.addListener(SWT.Dispose, disposeColumnListener);
			column.addListener(SWT.Move, resizeListener);
			column.addListener(SWT.Resize, resizeListener);
			tree.showColumn(column);
		}
		int columnIndex = column == null ? 0 : tree.indexOf(column);
		setBounds(row.getBounds(columnIndex));
		redraw();
		if (notify) notifyListeners(SWT.Selection, new Event());
	}
}

/**
 * Positions the TreeCursor over the root-level cell at the given row and column in the parent tree.
 *
 * @param row the index of the root-level row for the cell to select
 * @param column the index of column for the cell to select
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setSelection(int row, int column) {
	checkWidget();
	int columnCount = tree.getColumnCount();
	int maxColumnIndex = columnCount == 0 ? 0 : columnCount - 1;
	if (row < 0 || row >= tree.getItemCount() || column < 0 || column > maxColumnIndex) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	setRowColumn(row, column, false);
}

/**
 * Positions the TreeCursor over the cell at the given row and column in the parent tree.
 *
 * @param row the TreeItem of the row for the cell to select
 * @param column the index of column for the cell to select
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setSelection(TreeItem row, int column) {
	checkWidget();
	int columnCount = tree.getColumnCount();
	int maxColumnIndex = columnCount == 0 ? 0 : columnCount - 1;
	if (row == null || row.isDisposed() || column < 0 || column > maxColumnIndex) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	TreeColumn col = tree.getColumnCount() == 0 ? null : tree.getColumn(column);
	setRowColumn(row, col, false);
}

@Override
public void setVisible(boolean visible) {
	checkWidget();
	if (visible) {
		_resize();
	}
	super.setVisible(visible);
}

void treeCollapse(Event event) {
	if (row == null) return;
	TreeItem root = (TreeItem)event.item;
	TreeItem parentItem = row.getParentItem();
	while (parentItem != null) {
		if (parentItem == root) {
			setRowColumn(root, column, true);
			return;
		}
		parentItem = parentItem.getParentItem();
	}

	getDisplay().asyncExec(() -> {
		if (isDisposed()) return;
		setRowColumn(row, column, true);
	});
}

void treeExpand(Event event) {
	getDisplay().asyncExec(() -> {
		if (isDisposed()) return;
		setRowColumn(row, column, true);
	});
}

void treeFocusIn(Event event) {
	if (isVisible()) {
		if (row == null && column == null) return;
		setFocus();
	}
}

void treeMouseDown(Event event) {
	if (tree.getItemCount() == 0) return;
	Point pt = new Point(event.x, event.y);
	TreeItem item = tree.getItem(pt);
	if (item == null && (tree.getStyle() & SWT.FULL_SELECTION) == 0) {
		TreeItem currentItem = tree.getTopItem();
		TreeItem parentItem = currentItem.getParentItem();
		while (parentItem != null) {
			currentItem = parentItem;
			parentItem = currentItem.getParentItem();
		}
		int start = tree.indexOf(currentItem);
		int viewportItemCount = tree.getClientArea().height / tree.getItemHeight();
		int end = Math.min(start + viewportItemCount, tree.getItemCount() - 1);
		TreeItem[] allItems = tree.getItems();
		TreeItem[] items = new TreeItem[end - start + 1];
		System.arraycopy(allItems, start, items, 0, end - start + 1);
		item = findItem(items, pt);
	}
	if (item == null) return;

	TreeColumn newColumn = null;
	int lineWidth = tree.getLinesVisible() ? tree.getGridLineWidth() : 0;
	int columnCount = tree.getColumnCount();
	if (columnCount > 0) {
		for (int i = 0; i < columnCount; i++) {
			Rectangle rect = item.getBounds(i);
			rect.width += lineWidth;
			rect.height += lineWidth;
			if (rect.contains(pt)) {
				newColumn = tree.getColumn(i);
				break;
			}
		}
		if (newColumn == null) {
			newColumn = tree.getColumn(0);
		}
	}
	setRowColumn(item, newColumn, true);
	setFocus();
}

void unhookRowColumnListeners() {
	if (column != null && !column.isDisposed()) {
		column.removeListener(SWT.Dispose, disposeColumnListener);
		column.removeListener(SWT.Move, resizeListener);
		column.removeListener(SWT.Resize, resizeListener);
	}
	column = null;
	if (row != null && !row.isDisposed()) {
		TreeItem currentItem = row;
		while (currentItem != null) {
			currentItem.removeListener(SWT.Dispose, disposeItemListener);
			currentItem = currentItem.getParentItem();
		}
	}
	row = null;
}

}
