Mercurial > projects > dwt-mac
diff dwt/widgets/List.d @ 0:380af2bdd8e5
Upload of whole dwt tree
author | Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com> |
---|---|
date | Sat, 09 Aug 2008 17:00:02 +0200 |
parents | |
children | 649b8e223d5a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/widgets/List.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,1266 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 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 + *******************************************************************************/ +module dwt.widgets.List; + +import dwt.dwthelper.utils; + + +import dwt.DWT; +import dwt.DWTException; +import dwt.events.SelectionEvent; +import dwt.events.SelectionListener; +import dwt.graphics.Color; +import dwt.graphics.GC; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.internal.cocoa.NSAttributedString; +import dwt.internal.cocoa.NSColor; +import dwt.internal.cocoa.NSIndexSet; +import dwt.internal.cocoa.NSMutableDictionary; +import dwt.internal.cocoa.NSMutableIndexSet; +import dwt.internal.cocoa.NSPoint; +import dwt.internal.cocoa.NSRange; +import dwt.internal.cocoa.NSRect; +import dwt.internal.cocoa.NSString; +import dwt.internal.cocoa.NSTableColumn; +import dwt.internal.cocoa.NSTableView; +import dwt.internal.cocoa.OS; +import dwt.internal.cocoa.SWTScrollView; +import dwt.internal.cocoa.SWTTableView; + +/** + * Instances of this class represent a selectable user interface + * object that displays a list of strings and issues notification + * when a string is selected. A list may be single or multi select. + * <p> + * <dl> + * <dt><b>Styles:</b></dt> + * <dd>SINGLE, MULTI</dd> + * <dt><b>Events:</b></dt> + * <dd>Selection, DefaultSelection</dd> + * </dl> + * <p> + * Note: Only one of SINGLE and MULTI may be specified. + * </p><p> + * IMPORTANT: This class is <em>not</em> intended to be subclassed. + * </p> + */ +public class List extends Scrollable { + NSTableColumn column; + String [] items; + int itemCount; + bool ignoreSelect; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + * <p> + * The style value is either one of the style constants defined in + * class <code>DWT</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>DWT</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 composite 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 DWTException <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 DWT#SINGLE + * @see DWT#MULTI + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public List (Composite parent, int style) { + super (parent, checkStyle (style)); +} + +/** + * Adds the argument to the end of the receiver's list. + * + * @param string the new item + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the string is null</li> + * </ul> + * @exception DWTException <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 #add(String,int) + */ +public void add (String string) { + checkWidget(); + if (string is null) error (DWT.ERROR_NULL_ARGUMENT); + if (itemCount is items.length) { + String [] newItems = new String [itemCount + 4]; + System.arraycopy (items, 0, newItems, 0, items.length); + items = newItems; + } + items [itemCount++] = string; + ((NSTableView)view).reloadData(); + //TODO adjust horizontal scrollbar +} + +/** + * Adds the argument to the receiver's list at the given + * zero-relative index. + * <p> + * Note: To add an item at the end of the list, use the + * result of calling <code>getItemCount()</code> as the + * index or use <code>add(String)</code>. + * </p> + * + * @param string the new item + * @param index the index for the item + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the string is null</li> + * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)</li> + * </ul> + * @exception DWTException <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 #add(String) + */ +public void add (String string, int index) { + checkWidget(); + if (string is null) error (DWT.ERROR_NULL_ARGUMENT); + if (!(0 <= index && index <= itemCount)) error (DWT.ERROR_INVALID_RANGE); + if (index !is itemCount) fixSelection (index, true); + if (itemCount is items.length) { + String [] newItems = new String [itemCount + 4]; + System.arraycopy (items, 0, newItems, 0, items.length); + items = newItems; + } + System.arraycopy (items, index, items, index + 1, itemCount++ - index); + items [index] = string; + ((NSTableView)view).reloadData(); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the user changes the receiver's selection, by sending + * it one of the messages defined in the <code>SelectionListener</code> + * interface. + * <p> + * <code>widgetSelected</code> is called when the selection changes. + * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked. + * </p> + * + * @param listener the listener which should be notified when the user changes the receiver's selection + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception DWTException <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 #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener is null) error (DWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener(listener); + addListener(DWT.Selection,typedListener); + addListener(DWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0); +} + +public Point computeSize (int wHint, int hHint, bool changed) { + checkWidget(); + int width = 0; + if (wHint is DWT.DEFAULT) { + GC gc = new GC (this); + for (int i=0; i<itemCount; i++) { + Point extent = gc.stringExtent (items [i]); + width = Math.max (width, extent.x); + } + gc.dispose (); +// width += EXTRA_WIDTH; + } else { + width = wHint; + } + if (width <= 0) width = DEFAULT_WIDTH; + int height = 0; + if (hHint is DWT.DEFAULT) { + height = itemCount * getItemHeight (); + } else { + height = hHint; + } + if (height <= 0) height = DEFAULT_HEIGHT; + Rectangle rect = computeTrim (0, 0, width, height); + return new Point (rect.width, rect.height); +} + +void createHandle () { + SWTScrollView scrollWidget = (SWTScrollView)new SWTScrollView().alloc(); + scrollWidget.initWithFrame(new NSRect ()); + if ((style & DWT.H_SCROLL) !is 0) scrollWidget.setHasHorizontalScroller(true); + if ((style & DWT.V_SCROLL) !is 0) scrollWidget.setHasVerticalScroller(true); + scrollWidget.setAutohidesScrollers(true); + scrollWidget.setBorderType((style & DWT.BORDER) !is 0 ? OS.NSBezelBorder : OS.NSNoBorder); + scrollWidget.setTag(jniRef); + + NSTableView widget = (NSTableView)new SWTTableView().alloc(); + widget.initWithFrame(new NSRect()); + widget.setAllowsMultipleSelection((style & DWT.MULTI) !is 0); + widget.setDataSource(widget); + widget.setHeaderView(null); + widget.setDelegate(widget); + widget.setDoubleAction(OS.sel_sendDoubleSelection); + if (!hasBorder()) widget.setFocusRingType(OS.NSFocusRingTypeNone); + widget.setTag(jniRef); + + column = (NSTableColumn)new NSTableColumn().alloc(); + column.initWithIdentifier(NSString.stringWith("")); + widget.addTableColumn (column); + + scrollView = scrollWidget; + view = widget; + scrollView.setDocumentView(widget); + parent.contentView().addSubview_(scrollView); +} + +void createWidget () { + super.createWidget (); + items = new String [4]; +} + +Color defaultBackground () { + return display.getSystemColor (DWT.COLOR_LIST_BACKGROUND); +} + +Color defaultForeground () { + return display.getSystemColor (DWT.COLOR_LIST_FOREGROUND); +} + +/** + * Deselects the item at the given zero-relative index in the receiver. + * If the item at the index was already deselected, it remains + * deselected. Indices that are out of range are ignored. + * + * @param index the index of the item to deselect + * + * @exception DWTException <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 deselect (int index) { + checkWidget(); + if (0 <= index && index < itemCount) { + NSTableView widget = (NSTableView)view; + ignoreSelect = true; + widget.deselectRow (index); + ignoreSelect = false; + } +} + +/** + * Deselects the items at the given zero-relative indices in the receiver. + * If the item at the given zero-relative index in the receiver + * is selected, it is deselected. If the item at the index + * was not selected, it remains deselected. The range of the + * indices is inclusive. Indices that are out of range are ignored. + * + * @param start the start index of the items to deselect + * @param end the end index of the items to deselect + * + * @exception DWTException <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 deselect (int start, int end) { + checkWidget(); + if (start > end) return; + if (end < 0 || start >= itemCount) return; + start = Math.max (0, start); + end = Math.min (itemCount - 1, end); + int length = end - start + 1; + if (length <= 0) return; + if (start is 0 && end is itemCount - 1) { + deselectAll (); + } else { + NSTableView widget = (NSTableView)view; + ignoreSelect = true; + for (int i=0; i<length; i++) { + widget.deselectRow (i); + } + ignoreSelect = false; + } +} + +/** + * Deselects the items at the given zero-relative indices in the receiver. + * If the item at the given zero-relative index in the receiver + * is selected, it is deselected. If the item at the index + * was not selected, it remains deselected. Indices that are out + * of range and duplicate indices are ignored. + * + * @param indices the array of indices for the items to deselect + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the set of indices is null</li> + * </ul> + * @exception DWTException <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 deselect (int [] indices) { + checkWidget(); + if (indices is null) error (DWT.ERROR_NULL_ARGUMENT); + NSTableView widget = (NSTableView)view; + ignoreSelect = true; + for (int i=0; i<indices.length; i++) { + widget.deselectRow (indices [i]); + } + ignoreSelect = false; +} + +/** + * Deselects all selected items in the receiver. + * + * @exception DWTException <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 deselectAll () { + checkWidget (); + NSTableView widget = (NSTableView)view; + ignoreSelect = true; + widget.deselectAll(null); + ignoreSelect = false; +} + +void fixSelection (int index, bool add) { + int [] selection = getSelectionIndices (); + if (selection.length is 0) return; + int newCount = 0; + bool fix = false; + for (int i = 0; i < selection.length; i++) { + if (!add && selection [i] is index) { + fix = true; + } else { + int newIndex = newCount++; + selection [newIndex] = selection [i] + 1; + if (selection [newIndex] - 1 >= index) { + selection [newIndex] += add ? 1 : -1; + fix = true; + } + } + } + if (fix) select (selection, newCount, true); +} + +/** + * Returns the zero-relative index of the item which currently + * has the focus in the receiver, or -1 if no item has focus. + * + * @return the index of the selected item + * + * @exception DWTException <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 getFocusIndex () { + checkWidget(); +// int [] first = new int [1], last = new int [1]; +// if (OS.GetDataBrowserSelectionAnchor (handle, first, last) !is OS.noErr) return -1; +// return first [0] - 1; + return -1; +} + +/** + * Returns the item at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li> + * </ul> + * @exception DWTException <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 String getItem (int index) { + checkWidget(); + if (!(0 <= index && index < itemCount)) error (DWT.ERROR_INVALID_RANGE); + return items [index]; +} + +/** + * Returns the number of items contained in the receiver. + * + * @return the number of items + * + * @exception DWTException <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 getItemCount () { + checkWidget(); + return itemCount; +} + +/** + * Returns the height of the area which would be used to + * display <em>one</em> of the items in the list. + * + * @return the height of one item + * + * @exception DWTException <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 getItemHeight () { + checkWidget (); + return (int)((NSTableView)view).rowHeight(); +} + +/** + * Returns a (possibly empty) array of <code>String</code>s which + * are the items in the receiver. + * <p> + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + * </p> + * + * @return the items in the receiver's list + * + * @exception DWTException <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 String [] getItems () { + checkWidget(); + String [] result = new String [itemCount]; + System.arraycopy (items, 0, result, 0, itemCount); + return result; +} + +/** + * Returns an array of <code>String</code>s that are currently + * selected in the receiver. The order of the items is unspecified. + * An empty array indicates that no items are selected. + * <p> + * Note: This is not the actual structure used by the receiver + * to maintain its selection, so modifying the array will + * not affect the receiver. + * </p> + * @return an array representing the selection + * + * @exception DWTException <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 String [] getSelection () { + checkWidget (); + NSTableView widget = (NSTableView)view; + if (widget.numberOfSelectedRows() is 0) { + return new String [0]; + } + NSIndexSet selection = widget.selectedRowIndexes(); + int count = selection.count(); + int [] indexBuffer = new int [count]; + selection.getIndexes(indexBuffer, count, 0); + String [] result = new String [count]; + for (int i=0; i<count; i++) { + result [i] = items [indexBuffer [i]]; + } + return result; +} + +/** + * Returns the number of selected items contained in the receiver. + * + * @return the number of selected items + * + * @exception DWTException <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 getSelectionCount () { + checkWidget (); + return ((NSTableView)view).numberOfSelectedRows(); +} + +/** + * Returns the zero-relative index of the item which is currently + * selected in the receiver, or -1 if no item is selected. + * + * @return the index of the selected item or -1 + * + * @exception DWTException <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 getSelectionIndex () { + checkWidget(); + //TODO - check empty selection case + return ((NSTableView)view).selectedRow(); +} + +/** + * Returns the zero-relative indices of the items which are currently + * selected in the receiver. The order of the indices is unspecified. + * The array is empty if no items are selected. + * <p> + * Note: This is not the actual structure used by the receiver + * to maintain its selection, so modifying the array will + * not affect the receiver. + * </p> + * @return the array of indices of the selected items + * + * @exception DWTException <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 [] getSelectionIndices () { + checkWidget (); + NSTableView widget = (NSTableView)view; + if (widget.numberOfSelectedRows() is 0) { + return new int [0]; + } + NSIndexSet selection = widget.selectedRowIndexes(); + int count = selection.count(); + int [] result = new int [count]; + selection.getIndexes(result, count, 0); + return result; +} + +/** + * Returns the zero-relative index of the item which is currently + * at the top of the receiver. This index can change when items are + * scrolled or new items are added or removed. + * + * @return the index of the top item + * + * @exception DWTException <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 getTopIndex () { + checkWidget(); + //TODO - partial item at the top + NSRect rect = scrollView.documentVisibleRect(); + NSPoint point = new NSPoint(); + point.x = rect.x; + point.y = rect.y; + return ((NSTableView)view).rowAtPoint(point); +} + +/** + * Gets the index of an item. + * <p> + * The list is searched starting at 0 until an + * item is found that is equal to the search item. + * If no item is found, -1 is returned. Indexing + * is zero based. + * + * @param string the search item + * @return the index of the item + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the string is null</li> + * </ul> + * @exception DWTException <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 indexOf (String item) { + checkWidget(); + if (item is null) error (DWT.ERROR_NULL_ARGUMENT); + for (int i=0; i<itemCount; i++) { + if (items [i].equals (item)) return i; + } + return -1; +} + +/** + * Searches the receiver's list starting at the given, + * zero-relative index until an item is found that is equal + * to the argument, and returns the index of that item. If + * no item is found or the starting index is out of range, + * returns -1. + * + * @param string the search item + * @param start the zero-relative index at which to start the search + * @return the index of the item + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the string is null</li> + * </ul> + * @exception DWTException <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 indexOf (String string, int start) { + checkWidget(); + if (string is null) error (DWT.ERROR_NULL_ARGUMENT); + for (int i=start; i<itemCount; i++) { + if (items [i].equals (string)) return i; + } + return -1; +} + +/** + * Returns <code>true</code> if the item is selected, + * and <code>false</code> otherwise. Indices out of + * range are ignored. + * + * @param index the index of the item + * @return the selection state of the item at the index + * + * @exception DWTException <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 bool isSelected (int index) { + checkWidget(); + //TODO - range check + return ((NSTableView)view).isRowSelected(index); +} + +int numberOfRowsInTableView(int aTableView) { + return itemCount; +} + +void releaseHandle () { + super.releaseHandle (); + if (column !is null) column.release(); + column = null; +} + +void releaseWidget () { + super.releaseWidget (); + items = null; +} + +/** + * Removes the item from the receiver at the given + * zero-relative index. + * + * @param index the index for the item + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li> + * </ul> + * @exception DWTException <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 remove (int index) { + checkWidget(); + if (!(0 <= index && index < itemCount)) error (DWT.ERROR_INVALID_RANGE); + if (index !is itemCount - 1) fixSelection (index, false); + System.arraycopy (items, index + 1, items, index, --itemCount - index); + items [itemCount] = null; + ((NSTableView)view).noteNumberOfRowsChanged(); +} + +/** + * Removes the items from the receiver which are + * between the given zero-relative start and end + * indices (inclusive). + * + * @param start the start of the range + * @param end the end of the range + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</li> + * </ul> + * @exception DWTException <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 remove (int start, int end) { + checkWidget(); + if (start > end) return; + if (!(0 <= start && start <= end && end < itemCount)) { + error (DWT.ERROR_INVALID_RANGE); + } + int length = end - start + 1; + for (int i=0; i<length; i++) remove (start); +} + +/** + * Searches the receiver's list starting at the first item + * until an item is found that is equal to the argument, + * and removes that item from the list. + * + * @param string the item to remove + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the string is null</li> + * <li>ERROR_INVALID_ARGUMENT - if the string is not found in the list</li> + * </ul> + * @exception DWTException <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 remove (String string) { + checkWidget(); + if (string is null) error (DWT.ERROR_NULL_ARGUMENT); + int index = indexOf (string, 0); + if (index is -1) error (DWT.ERROR_INVALID_ARGUMENT); + remove (index); +} + +/** + * Removes the items from the receiver at the given + * zero-relative indices. + * + * @param indices the array of indices of the items + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li> + * <li>ERROR_NULL_ARGUMENT - if the indices array is null</li> + * </ul> + * @exception DWTException <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 remove (int [] indices) { + checkWidget (); + if (indices is null) error (DWT.ERROR_NULL_ARGUMENT); + if (indices.length is 0) return; + int [] newIndices = new int [indices.length]; + System.arraycopy (indices, 0, newIndices, 0, indices.length); + sort (newIndices); + int start = newIndices [newIndices.length - 1], end = newIndices [0]; + int count = getItemCount (); + if (!(0 <= start && start <= end && end < count)) { + error (DWT.ERROR_INVALID_RANGE); + } + int last = -1; + for (int i=0; i<newIndices.length; i++) { + int index = newIndices [i]; + if (index !is last) { + remove (index); + last = index; + } + } +} + +/** + * Removes all of the items from the receiver. + * <p> + * @exception DWTException <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 removeAll () { + checkWidget(); + items = new String [4]; + itemCount = 0; + ((NSTableView)view).noteNumberOfRowsChanged(); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the user changes the receiver's selection. + * + * @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 DWTException <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 + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener is null) error (DWT.ERROR_NULL_ARGUMENT); + if (eventTable is null) return; + eventTable.unhook(DWT.Selection, listener); + eventTable.unhook(DWT.DefaultSelection,listener); +} + +/** + * Selects the item at the given zero-relative index in the receiver's + * list. If the item at the index was already selected, it remains + * selected. Indices that are out of range are ignored. + * + * @param index the index of the item to select + * + * @exception DWTException <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 select (int index) { + checkWidget(); + if (0 <= index && index < itemCount) { + NSIndexSet indexes = (NSIndexSet)new NSIndexSet().alloc(); + indexes.initWithIndex(index); + NSTableView widget = (NSTableView)view; + ignoreSelect = true; + ((NSTableView)view).selectRowIndexes(indexes, true); + ignoreSelect = false; + } +} + +/** + * Selects the items in the range specified by the given zero-relative + * indices in the receiver. The range of indices is inclusive. + * The current selection is not cleared before the new items are selected. + * <p> + * If an item in the given range is not selected, it is selected. + * If an item in the given range was already selected, it remains selected. + * Indices that are out of range are ignored and no items will be selected + * if start is greater than end. + * If the receiver is single-select and there is more than one item in the + * given range, then all indices are ignored. + * + * @param start the start of the range + * @param end the end of the range + * + * @exception DWTException <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 List#setSelection(int,int) + */ +public void select (int start, int end) { + checkWidget (); + if (end < 0 || start > end || ((style & DWT.SINGLE) !is 0 && start !is end)) return; + if (itemCount is 0 || start >= itemCount) return; + if (start is 0 && end is itemCount - 1) { + selectAll (); + } else { + start = Math.max (0, start); + end = Math.min (end, itemCount - 1); + int length = end - start + 1; + NSIndexSet indexes = (NSIndexSet)new NSIndexSet().alloc(); + NSRange range = new NSRange(); + range.location = start; + range.length = length; + indexes.initWithIndexesInRange(range); + NSTableView widget = (NSTableView)view; + ignoreSelect = true; + widget.selectRowIndexes(indexes, true); + ignoreSelect = false; + } +} + +/** + * Selects the items at the given zero-relative indices in the receiver. + * The current selection is not cleared before the new items are selected. + * <p> + * If the item at a given index is not selected, it is selected. + * If the item at a given index was already selected, it remains selected. + * Indices that are out of range and duplicate indices are ignored. + * If the receiver is single-select and multiple indices are specified, + * then all indices are ignored. + * + * @param indices the array of indices for the items to select + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the array of indices is null</li> + * </ul> + * @exception DWTException <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 List#setSelection(int[]) + */ +public void select (int [] indices) { + checkWidget (); + if (indices is null) error (DWT.ERROR_NULL_ARGUMENT); + int length = indices.length; + if (length is 0 || ((style & DWT.SINGLE) !is 0 && length > 1)) return; + int count = 0; + NSMutableIndexSet indexes = (NSMutableIndexSet)new NSMutableIndexSet().alloc().init(); + for (int i=0; i<length; i++) { + int index = indices [length - i - 1]; + if (index >= 0 && index < itemCount) { + indexes.addIndex (indices [i]); + count++; + } + } + if (count > 0) { + NSTableView widget = (NSTableView)view; + ignoreSelect = true; + widget.selectRowIndexes(indexes, true); + ignoreSelect = false; + } +} + +void select (int [] ids, int count, bool clear) { + NSMutableIndexSet indexes = (NSMutableIndexSet)new NSMutableIndexSet().alloc().init(); + for (int i=0; i<count; i++) indexes.addIndex (ids [i] - 1); //WRONG -1 + NSTableView widget = (NSTableView)view; + ignoreSelect = true; + widget.selectRowIndexes(indexes, !clear); + ignoreSelect = false; +} + +/** + * Selects all of the items in the receiver. + * <p> + * If the receiver is single-select, do nothing. + * + * @exception DWTException <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 selectAll () { + checkWidget (); + if ((style & DWT.SINGLE) !is 0) return; + NSTableView widget = (NSTableView)view; + ignoreSelect = true; + widget.selectAll(null); + ignoreSelect = false; +} + +void sendDoubleSelection() { + postEvent (DWT.DefaultSelection); +} + +/** + * Sets the text of the item in the receiver's list at the given + * zero-relative index to the string argument. + * + * @param index the index for the item + * @param string the new text for the item + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li> + * <li>ERROR_NULL_ARGUMENT - if the string is null</li> + * </ul> + * @exception DWTException <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 setItem (int index, String string) { + checkWidget(); + if (string is null) error (DWT.ERROR_NULL_ARGUMENT); + if (!(0 <= index && index < itemCount)) error (DWT.ERROR_INVALID_RANGE); + items [index] = string; + ((NSTableView)view).reloadData(); +} + +/** + * Sets the receiver's items to be the given array of items. + * + * @param items the array of items + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the items array is null</li> + * <li>ERROR_INVALID_ARGUMENT - if an item in the items array is null</li> + * </ul> + * @exception DWTException <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 setItems (String [] items) { + checkWidget(); + if (items is null) error (DWT.ERROR_NULL_ARGUMENT); + for (int i=0; i<items.length; i++) { + if (items [i] is null) error (DWT.ERROR_INVALID_ARGUMENT); + } + this.items = new String [items.length]; + System.arraycopy (items, 0, this.items, 0, items.length); + itemCount = items.length; + ((NSTableView)view).reloadData(); +} + +/** + * Selects the item at the given zero-relative index in the receiver. + * If the item at the index was already selected, it remains selected. + * The current selection is first cleared, then the new item is selected. + * Indices that are out of range are ignored. + * + * @param index the index of the item to select + * + * @exception DWTException <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 List#deselectAll() + * @see List#select(int) + */ +public void setSelection (int index) { + checkWidget(); + deselectAll (); + setSelection (index, false); +} + +void setSelection (int index, bool notify) { +// checkWidget(); + if (0 <= index && index < itemCount) { + int [] ids = new int [] {index + 1}; + select (ids, ids.length, true); + showIndex (index); + if (notify) postEvent (DWT.Selection); + } +} + +/** + * Selects the items in the range specified by the given zero-relative + * indices in the receiver. The range of indices is inclusive. + * The current selection is cleared before the new items are selected. + * <p> + * Indices that are out of range are ignored and no items will be selected + * if start is greater than end. + * If the receiver is single-select and there is more than one item in the + * given range, then all indices are ignored. + * + * @param start the start index of the items to select + * @param end the end index of the items to select + * + * @exception DWTException <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 List#deselectAll() + * @see List#select(int,int) + */ +public void setSelection (int start, int end) { + checkWidget (); + deselectAll (); + if (end < 0 || start > end || ((style & DWT.SINGLE) !is 0 && start !is end)) return; + if (itemCount is 0 || start >= itemCount) return; + start = Math.max (0, start); + end = Math.min (end, itemCount - 1); + int length = end - start + 1; + int [] ids = new int [length]; + for (int i=0; i<length; i++) ids [i] = end - i + 1; + select (ids, length, true); + if (ids.length > 0) showIndex (ids [0] - 1); +} + +/** + * Selects the items at the given zero-relative indices in the receiver. + * The current selection is cleared before the new items are selected. + * <p> + * Indices that are out of range and duplicate indices are ignored. + * If the receiver is single-select and multiple indices are specified, + * then all indices are ignored. + * + * @param indices the indices of the items to select + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the array of indices is null</li> + * </ul> + * @exception DWTException <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 List#deselectAll() + * @see List#select(int[]) + */ +public void setSelection (int [] indices) { + checkWidget (); + if (indices is null) error (DWT.ERROR_NULL_ARGUMENT); + deselectAll (); + int length = indices.length; + if (length is 0 || ((style & DWT.SINGLE) !is 0 && length > 1)) return; + int [] ids = new int [length]; + int count = 0; + for (int i=0; i<length; i++) { + int index = indices [length - i - 1]; + if (index >= 0 && index < itemCount) { + ids [count++] = index + 1; + } + } + if (count > 0) { + select (ids, count, true); + showIndex (ids [0] - 1); + } +} + +/** + * Sets the receiver's selection to be the given array of items. + * The current selection is cleared before the new items are selected. + * <p> + * Items that are not in the receiver are ignored. + * If the receiver is single-select and multiple items are specified, + * then all items are ignored. + * + * @param items the array of items + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the array of items is null</li> + * </ul> + * @exception DWTException <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 List#deselectAll() + * @see List#select(int[]) + * @see List#setSelection(int[]) + */ +public void setSelection (String [] items) { + checkWidget (); + if (items is null) error (DWT.ERROR_NULL_ARGUMENT); + deselectAll (); + int length = items.length; + if (length is 0 || ((style & DWT.SINGLE) !is 0 && length > 1)) return; + int count = 0; + int [] ids = new int [length]; + for (int i=0; i<length; i++) { + String string = items [length - i - 1]; + if ((style & DWT.SINGLE) !is 0) { + int index = indexOf (string, 0); + if (index !is -1) { + count = 1; + ids = new int [] {index + 1}; + } + } else { + int index = 0; + while ((index = indexOf (string, index)) !is -1) { + if (count is ids.length) { + int [] newIds = new int [ids.length + 4]; + System.arraycopy (ids, 0, newIds, 0, ids.length); + ids = newIds; + } + ids [count++] = index + 1; + index++; + } + } + } + if (count > 0) { + select (ids, count, true); + showIndex (ids [0] - 1); + } +} + +/** + * Sets the zero-relative index of the item which is currently + * at the top of the receiver. This index can change when items + * are scrolled or new items are added and removed. + * + * @param index the index of the top item + * + * @exception DWTException <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 setTopIndex (int index) { + checkWidget(); + NSRect rect = ((NSTableView)view).rectOfRow(index); + ((NSTableView)view).scrollRectToVisible(rect); +} + +void showIndex (int index) { + if (0 <= index && index < itemCount) { + ((NSTableView)view).scrollRowToVisible(index); + } +} + +/** + * Shows the selection. If the selection is already showing in the receiver, + * this method simply returns. Otherwise, the items are scrolled until + * the selection is visible. + * + * @exception DWTException <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 showSelection () { + checkWidget(); + int index = getSelectionIndex (); + if (index >= 0) showIndex (index); +} + +void tableViewSelectionDidChange (int aNotification) { + if (ignoreSelect) return; + postEvent (DWT.Selection); +} + +bool tableView_shouldEditTableColumn_row(int aTableView, int aTableColumn, int rowIndex) { + return false; +} + +int tableView_objectValueForTableColumn_row(int aTableView, int aTableColumn, int rowIndex) { + NSMutableDictionary dict = NSMutableDictionary.dictionaryWithCapacity(4); + if (foreground !is null) { + NSColor color = NSColor.colorWithDeviceRed(foreground.handle[0], foreground.handle[1], foreground.handle[2], 1); + dict.setObject(color, OS.NSForegroundColorAttributeName()); + } + if (font !is null) { + dict.setObject(font.handle, OS.NSFontAttributeName()); + } + if (background !is null) { + NSColor color = NSColor.colorWithDeviceRed(background.handle[0], background.handle[1], background.handle[2], 1); + dict.setObject(color, OS.NSBackgroundColorAttributeName()); + } + String text = items[rowIndex]; + int length = text.length(); + char[] chars = new char[length]; + text.getChars(0, length, chars, 0); + NSString str = NSString.stringWithCharacters(chars, length); + NSAttributedString attribStr = ((NSAttributedString)new NSAttributedString().alloc()).initWithString_attributes_(str, dict); + attribStr.autorelease(); + return attribStr.id; +} + +}