diff options
author | Bogdan Gheorghe <gheorghe@ca.ibm.com> | 2012-04-11 15:30:43 -0400 |
---|---|---|
committer | Bogdan Gheorghe <gheorghe@ca.ibm.com> | 2012-04-11 15:30:43 -0400 |
commit | ee4f0bb6b23599d83c79fb3b20fab9ba5aea3678 (patch) | |
tree | d194662c5a14f43000c5178883b755a5a60d93b3 /bundles/org.eclipse.swt/Eclipse SWT Custom Widgets | |
parent | 61d3fcafc6913ab75f5e11bcd4fbea9e08995c42 (diff) | |
download | eclipse.platform.swt-ee4f0bb6b23599d83c79fb3b20fab9ba5aea3678.tar.gz eclipse.platform.swt-ee4f0bb6b23599d83c79fb3b20fab9ba5aea3678.tar.xz eclipse.platform.swt-ee4f0bb6b23599d83c79fb3b20fab9ba5aea3678.zip |
Convert all files with CRLF and CR to LF
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT Custom Widgets')
-rw-r--r-- | bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TreeCursor.java | 1926 |
1 files changed, 963 insertions, 963 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TreeCursor.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TreeCursor.java index a15f4041c9..8c01ac4934 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TreeCursor.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TreeCursor.java @@ -1,963 +1,963 @@ -/*******************************************************************************
- * Copyright (c) 2011 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() {
- 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() {
- 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() {
- 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() {
- 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() {
- 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() {
- public void getRole(AccessibleControlEvent e) {
- e.detail = ACC.ROLE_TABLECELL;
- }
- });
- getAccessible().addAccessibleListener(new AccessibleAdapter() {
- 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
- */
-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
- */
-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>
- */
-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>
- */
-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);
-}
-
-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() {
- public void run() {
- if (isDisposed()) return;
- setRowColumn(row, column, true);
- }
- });
-}
-
-void treeExpand(Event event) {
- getDisplay().asyncExec(new Runnable() {
- 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;
-}
-
-}
+/******************************************************************************* + * Copyright (c) 2011 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() { + 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() { + 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() { + 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() { + 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() { + 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() { + public void getRole(AccessibleControlEvent e) { + e.detail = ACC.ROLE_TABLECELL; + } + }); + getAccessible().addAccessibleListener(new AccessibleAdapter() { + 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 + */ +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 + */ +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> + */ +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> + */ +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); +} + +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() { + public void run() { + if (isDisposed()) return; + setRowColumn(row, column, true); + } + }); +} + +void treeExpand(Event event) { + getDisplay().asyncExec(new Runnable() { + 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; +} + +} |