/*******************************************************************************
 * 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 = new Listener() {
		@Override
		public void handleEvent(Event 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 = new Listener() {
		@Override
		public void handleEvent(Event 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 = new Listener() {
		@Override
		public void handleEvent(Event 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 = new Listener() {
		@Override
		public void handleEvent(Event 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 = new Listener() {
		@Override
		public void handleEvent(Event 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(new Runnable() {
		@Override
		public void run() {
			if (isDisposed()) return;
			setRowColumn(row, column, true);
		}
	});
}

void treeExpand(Event event) {
	getDisplay().asyncExec(new Runnable() {
		@Override
		public void run() {
			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;
}

}
