diff dwt/widgets/Table.d @ 45:d8635bb48c7c

Merge with SWT 3.5
author Jacob Carlborg <doob@me.com>
date Mon, 01 Dec 2008 17:07:00 +0100
parents e831403a80a9
children cfa563df4fdd
line wrap: on
line diff
--- a/dwt/widgets/Table.d	Tue Oct 21 15:20:04 2008 +0200
+++ b/dwt/widgets/Table.d	Mon Dec 01 17:07:00 2008 +0100
@@ -1,5 +1,5 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2007 IBM Corporation and others.
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
@@ -12,33 +12,50 @@
 
 import dwt.dwthelper.utils;
 
-
 import dwt.DWT;
 import dwt.DWTException;
+import dwt.accessibility.ACC;
 import dwt.events.SelectionEvent;
 import dwt.events.SelectionListener;
 import dwt.graphics.Color;
 import dwt.graphics.Font;
 import dwt.graphics.GC;
+import dwt.graphics.GCData;
 import dwt.graphics.Image;
 import dwt.graphics.Point;
 import dwt.graphics.Rectangle;
+import dwt.internal.cocoa.NSArray;
+import dwt.internal.cocoa.NSBezierPath;
 import dwt.internal.cocoa.NSBrowserCell;
 import dwt.internal.cocoa.NSButtonCell;
-import dwt.internal.cocoa.NSCell;
+import dwt.internal.cocoa.NSColor;
+import dwt.internal.cocoa.NSColorSpace;
+import dwt.internal.cocoa.NSDictionary;
+import dwt.internal.cocoa.NSEvent;
+import dwt.internal.cocoa.NSFont;
+import dwt.internal.cocoa.NSGraphicsContext;
 import dwt.internal.cocoa.NSIndexSet;
 import dwt.internal.cocoa.NSMutableIndexSet;
+import dwt.internal.cocoa.NSNotification;
 import dwt.internal.cocoa.NSNumber;
 import dwt.internal.cocoa.NSPoint;
 import dwt.internal.cocoa.NSRange;
 import dwt.internal.cocoa.NSRect;
+import dwt.internal.cocoa.NSScrollView;
+import dwt.internal.cocoa.NSSize;
 import dwt.internal.cocoa.NSString;
 import dwt.internal.cocoa.NSTableColumn;
+import dwt.internal.cocoa.NSTableHeaderCell;
 import dwt.internal.cocoa.NSTableHeaderView;
 import dwt.internal.cocoa.NSTableView;
+import dwt.internal.cocoa.NSView;
 import dwt.internal.cocoa.OS;
+import dwt.internal.cocoa.SWTBrowserCell;
 import dwt.internal.cocoa.SWTScrollView;
+import dwt.internal.cocoa.SWTTableHeaderCell;
+import dwt.internal.cocoa.SWTTableHeaderView;
 import dwt.internal.cocoa.SWTTableView;
+import dwt.internal.cocoa.id;
 
 /** 
  * Instances of this class implement a selectable user interface
@@ -69,12 +86,13 @@
  * </pre></code>
  * </p><p>
  * Note that although this class is a subclass of <code>Composite</code>,
- * it does not make sense to add <code>Control</code> children to it,
- * or set a layout on it.
+ * it does not normally make sense to add <code>Control</code> children to
+ * it, or set a layout on it, unless implementing something like a cell
+ * editor.
  * </p><p>
  * <dl>
  * <dt><b>Styles:</b></dt>
- * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION, VIRTUAL</dd>
+ * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION, VIRTUAL, NO_SCROLL</dd>
  * <dt><b>Events:</b></dt>
  * <dd>Selection, DefaultSelection, SetData, MeasureItem, EraseItem, PaintItem</dd>
  * </dl>
@@ -83,6 +101,10 @@
  * </p><p>
  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
  * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#table">Table, TableItem, TableColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
  */
 public class Table : Composite {
     TableItem [] items;
@@ -91,6 +113,7 @@
     TableItem currentItem;
     NSTableHeaderView headerView;
     NSTableColumn firstColumn, checkColumn;
+    NSBrowserCell dataCell;
     int columnCount, itemCount, lastIndexOf, sortDirection;
     bool ignoreSelect;
 
@@ -124,6 +147,7 @@
  * @see DWT#FULL_SELECTION
  * @see DWT#HIDE_SELECTION
  * @see DWT#VIRTUAL
+ * @see DWT#NO_SCROLL
  * @see Widget#checkSubclass
  * @see Widget#getStyle
  */
@@ -131,6 +155,25 @@
     super (parent, checkStyle (style));
 }
 
+int accessibilityAttributeValue (int /*long*/ id, int /*long*/ sel, int /*long*/ arg0) {
+    
+    if (accessible !is null) {
+        NSString attribute = new NSString(arg0);
+        id returnValue = accessible.internal_accessibilityAttributeValue(attribute, ACC.CHILDID_SELF);
+        if (returnValue !is null) return returnValue.id;
+    }
+    
+    NSString attributeName = new NSString(arg0);
+    
+    // Accessibility Verifier queries for a title or description.  NSTableView doesn't
+    // seem to return either, so we return a default description value here.
+    if (attributeName.isEqualToString (OS.NSAccessibilityDescriptionAttribute)) {
+        return NSString.stringWith("").id;
+    }
+    
+    return super.accessibilityAttributeValue(id, sel, arg0);
+}
+
 /**
  * Adds the listener to the collection of listeners who will
  * be notified when the user changes the receiver's selection, by sending
@@ -233,19 +276,15 @@
  * @since 3.0
  */
 public void clear (int index) {
-    checkWidget();
+    checkWidget ();
     if (!(0 <= index && index < itemCount)) error (DWT.ERROR_INVALID_RANGE);
     TableItem item = items [index];
     if (item !is null) {
-        if (currentItem !is item) item.clear ();
-        if (currentItem is null && drawCount is 0) {
-            int [] id = new int [] {index + 1};
-//          OS.UpdateDataBrowserItems (handle, 0, id.length, id, OS.kDataBrowserItemNoProperty, OS.kDataBrowserNoItem);
-        }
-//      setScrollWidth (item);
+        item.clear ();
+        NSTableView widget = (NSTableView) view;
+        widget.reloadData ();
     }
 }
-
 /**
  * Removes the items from the receiver which are between the given
  * zero-relative start and end indices (inclusive).  The text, icon
@@ -270,7 +309,7 @@
  * @since 3.0
  */
 public void clear (int start, int end) {
-    checkWidget();
+    checkWidget ();
     if (start > end) return;
     if (!(0 <= start && start <= end && end < itemCount)) {
         error (DWT.ERROR_INVALID_RANGE);
@@ -279,8 +318,11 @@
         clearAll ();
     } else {
         for (int i=start; i<=end; i++) {
-            clear (i);
+            TableItem item = items [i];
+            if (item !is null) item.clear ();
         }
+        NSTableView widget = (NSTableView) view;
+        widget.reloadData ();
     }
 }
 
@@ -307,7 +349,7 @@
  * @since 3.0
  */
 public void clear (int [] indices) {
-    checkWidget();
+    checkWidget ();
     if (indices is null) error (DWT.ERROR_NULL_ARGUMENT);
     if (indices.length is 0) return;
     for (int i=0; i<indices.length; i++) {
@@ -316,8 +358,11 @@
         }
     }
     for (int i=0; i<indices.length; i++) {
-        clear (indices [i]);
+        TableItem item = items [indices [i]];
+        if (item !is null) item.clear ();
     }
+    NSTableView widget = (NSTableView) view;
+    widget.reloadData ();
 }
 
 /**
@@ -337,19 +382,17 @@
  * @since 3.0
  */
 public void clearAll () {
-    checkWidget();
+    checkWidget ();
     for (int i=0; i<itemCount; i++) {
         TableItem item = items [i];
         if (item !is null) item.clear ();
     }
-    if (currentItem is null && drawCount is 0) {
-//      OS.UpdateDataBrowserItems (handle, 0, 0, null, OS.kDataBrowserItemNoProperty, OS.kDataBrowserNoItem);
-    }
-//  setScrollWidth (items, true);
+    NSTableView widget = (NSTableView) view;
+    widget.reloadData ();
 }
 
 public Point computeSize (int wHint, int hHint, bool changed) {
-    checkWidget();
+    checkWidget ();
     int width = 0;
     if (wHint is DWT.DEFAULT) {
         if (columnCount !is 0) {
@@ -362,7 +405,7 @@
             for (int i=0; i<itemCount; i++) {
                 TableItem item = items [i];
                 if (item !is null) {
-                    columnWidth = Math.max (columnWidth, item.calculateWidth (0, gc));
+                    columnWidth = Math.max (columnWidth, item.calculateWidth (0, gc, false));
                 }
             }
             gc.dispose ();
@@ -385,32 +428,29 @@
 }
 
 void createHandle () {
-    //TODO - DWT.CHECK  
-    SWTScrollView scrollWidget = cast(SWTScrollView)new SWTScrollView().alloc();
+    NSScrollView scrollWidget = (NSScrollView)new SWTScrollView().alloc();
     scrollWidget.initWithFrame(new NSRect ());
     scrollWidget.setHasHorizontalScroller(true);
     scrollWidget.setHasVerticalScroller(true);
     scrollWidget.setAutohidesScrollers(true);
     scrollWidget.setBorderType(hasBorder() ? OS.NSBezelBorder : OS.NSNoBorder);
-    scrollWidget.setTag(jniRef);
     
     NSTableView widget = cast(NSTableView)new SWTTableView().alloc();
     widget.initWithFrame(new NSRect());
     widget.setAllowsMultipleSelection((style & DWT.MULTI) !is 0);
+    widget.setAllowsColumnReordering (false);
     widget.setDataSource(widget);
     widget.setDelegate(widget);
     widget.setDoubleAction(OS.sel_sendDoubleSelection);
     if (!hasBorder()) widget.setFocusRingType(OS.NSFocusRingTypeNone);
-    widget.setTag(jniRef);
-    
-    headerView = widget.headerView();
-    headerView.retain();
-    widget.setHeaderView(null);
-    
+
+    headerView = (NSTableHeaderView)new SWTTableHeaderView ().alloc ().init ();
+    widget.setHeaderView (null);
+
     NSString str = NSString.stringWith("");
     if ((style & DWT.CHECK) !is 0) {
         checkColumn = cast(NSTableColumn)new NSTableColumn().alloc();
-        checkColumn.initWithIdentifier(str);
+        checkColumn.initWithIdentifier(checkColumn);
         checkColumn.headerCell().setTitle(str);
         widget.addTableColumn (checkColumn);
         NSButtonCell cell = cast(NSButtonCell)new NSButtonCell().alloc().init();
@@ -425,17 +465,15 @@
     }
 
     firstColumn = cast(NSTableColumn)new NSTableColumn().alloc();
-    firstColumn.initWithIdentifier(str);
+    firstColumn.initWithIdentifier(firstColumn);
+    firstColumn.setMinWidth(0);
     //column.setResizingMask(OS.NSTableColumnAutoresizingMask);
-    NSCell cell = cast(NSBrowserCell)new NSBrowserCell().alloc().init();
-    firstColumn.setDataCell(cell);
-    cell.release();
+    dataCell = cast(NSBrowserCell)(new SWTBrowserCell ()).alloc ().init ();
+    firstColumn.setDataCell (dataCell);
     widget.addTableColumn (firstColumn);
 
     scrollView = scrollWidget;
     view = widget;
-    scrollView.setDocumentView(widget);
-    parent.contentView().addSubview_(scrollView);
 }
 
 void createItem (TableColumn column, int index) {
@@ -449,20 +487,22 @@
     if (columnCount is 0) {
         //TODO - clear attributes, alignment etc.
         nsColumn = firstColumn;
+        nsColumn.retain();
         firstColumn = null;
     } else {
         //TODO - set attributes, alignment etc.
         nsColumn = cast(NSTableColumn)new NSTableColumn().alloc();
-        nsColumn.initWithIdentifier(NSString.stringWith(""));
-        (cast(NSTableView)view).addTableColumn (nsColumn);
+        nsColumn.initWithIdentifier(nsColumn);
+        nsColumn.setMinWidth(0);
         int checkColumn = (style & DWT.CHECK) !is 0 ? 1 : 0;
         (cast(NSTableView)view).moveColumn (columnCount + checkColumn, index + checkColumn);
-        NSCell cell = cast(NSBrowserCell)new NSBrowserCell().alloc().init();
-        nsColumn.setDataCell(cell);
-        cell.release();
+        nsColumn.setDataCell (dataCell);
     }
+    column.createJNIRef ();
+    NSTableHeaderCell headerCell = (NSTableHeaderCell)new SWTTableHeaderCell ().alloc ().init ();
+    nsColumn.setHeaderCell (headerCell);
+    display.addWidget (headerCell, column);
     column.nsColumn = nsColumn;
-    nsColumn.headerCell().setTitle(NSString.stringWith(""));
     nsColumn.setWidth(0);
     System.arraycopy (columns, index, columns, index + 1, columnCount++ - index);
     columns [index] = column;
@@ -510,6 +550,10 @@
                 }
             }
         }
+    } else {
+        for (int i = 0; i < itemCount; i++) {
+            items [i].customWidth = -1;
+        }
     }
 }
 
@@ -542,6 +586,12 @@
     return display.getSystemColor (DWT.COLOR_LIST_FOREGROUND);
 }
 
+void deregister () {
+    super.deregister ();
+    display.removeWidget (headerView);
+    display.removeWidget (dataCell);
+}
+
 /**
  * Deselects the item at the given zero-relative index in the receiver.
  * If the item at the index was already deselected, it remains
@@ -555,7 +605,7 @@
  * </ul>
  */
 public void deselect (int index) {
-    checkWidget();
+    checkWidget ();
     if (0 <= index && index < itemCount) {
         NSTableView widget = cast(NSTableView)view;
         ignoreSelect = true;
@@ -581,14 +631,16 @@
  */
 public void deselect (int start, int end) {
     checkWidget();
-    //TODO - check range
+    if (start > end) return;
+    if (end < 0 || start >= itemCount) return;
+    start = Math.max (0, start);
+    end = Math.min (itemCount - 1, end);
     if (start is 0 && end is itemCount - 1) {
         deselectAll ();
     } else {
-        int length = end - start + 1;
         NSTableView widget = cast(NSTableView)view;
         ignoreSelect = true;
-        for (int i=0; i<length; i++) {
+        for (int i=start; i<=end; i++) {
             widget.deselectRow (i);
         }
         ignoreSelect = false;
@@ -613,7 +665,7 @@
  * </ul>
  */
 public void deselect (int [] indices) {
-    checkWidget();
+    checkWidget ();
     if (indices is null) error (DWT.ERROR_NULL_ARGUMENT);
     NSTableView widget = cast(NSTableView)view;
     ignoreSelect = true;
@@ -701,6 +753,9 @@
             }
         }
     }
+
+    int oldIndex = (int)/*64*/((NSTableView)view).columnWithIdentifier (column.nsColumn);
+
     if (columnCount is 1) {
         //TODO - reset attributes
         firstColumn = column.nsColumn;
@@ -710,8 +765,17 @@
     }
     System.arraycopy (columns, index + 1, columns, index, --columnCount - index);
     columns [columnCount] = null;
-    for (int i=index; i<columnCount; i++) {
-        columns [i].sendEvent (DWT.Move);
+
+    NSArray array = ((NSTableView)view).tableColumns ();
+    int arraySize = (int)/*64*/array.count ();
+    for (int i = oldIndex; i < arraySize; i++) {
+        int /*long*/ columnId = array.objectAtIndex (i).id;
+        for (int j = 0; j < columnCount; j++) {
+            if (columns[j].nsColumn.id is columnId) {
+                columns [j].sendEvent (DWT.Move);
+                break;
+            }
+        }
     }
 }
 
@@ -732,6 +796,199 @@
     }
 }
 
+void drawInteriorWithFrame_inView (int /*long*/ id, int /*long*/ sel, int /*long*/ cellFrame, int /*long*/ view) {
+    NSRect rect = new NSRect ();
+    OS.memmove (rect, cellFrame, NSRect.sizeof);
+
+    NSTableView tableView = (NSTableView)this.view;
+    NSBrowserCell cell = new NSBrowserCell (id);
+    NSRange rowsRange = tableView.rowsInRect (rect);
+    int rowIndex = (int)/*64*/rowsRange.location;
+    TableItem item = items [rowIndex];
+    int columnIndex = 0;
+    int nsColumnIndex = 0;
+    if (columnCount !is 0) {
+        NSIndexSet columnsSet = tableView.columnIndexesInRect (rect);
+        nsColumnIndex = (int)/*64*/columnsSet.firstIndex ();
+        NSArray nsColumns = tableView.tableColumns ();
+        id nsColumn = nsColumns.objectAtIndex (nsColumnIndex);
+        for (int i = 0; i < columnCount; i++) {
+            if (columns[i].nsColumn.id is nsColumn.id) {
+                columnIndex = indexOf (columns[i]);
+                break;
+            }
+        }
+    }
+
+    Color background = item.cellBackground !is null ? item.cellBackground [columnIndex] : null;
+    if (background is null) background = item.background;
+    bool drawBackground = background !is null;
+    bool drawForeground = true;
+    bool isSelected = tableView.isRowSelected (rowIndex);
+    bool drawSelection = isSelected;
+
+    NSColor nsSelectionBackground = null;
+    NSColor nsSelectionForeground = null;
+    if (isSelected) {
+        if (isFocusControl ()) {
+            nsSelectionForeground = NSColor.alternateSelectedControlTextColor ();
+        } else {
+            nsSelectionForeground = NSColor.selectedControlTextColor ();
+        }
+        nsSelectionForeground = nsSelectionForeground.colorUsingColorSpace (NSColorSpace.deviceRGBColorSpace ());
+        nsSelectionBackground = cell.highlightColorInView (tableView);
+        nsSelectionBackground = nsSelectionBackground.colorUsingColorSpace (NSColorSpace.deviceRGBColorSpace ());
+    }
+
+    NSRect fullRect = new NSRect ();
+    fullRect.x = rect.x; fullRect.y = rect.y; fullRect.height = rect.height;
+    if (columnCount is 0) {
+        if (item.customWidth !is -1) {
+            fullRect.width = item.customWidth;
+        } else {
+            NSSize contentSize = cell.cellSizeForBounds (rect);
+            fullRect.width = contentSize.width;
+        }
+    } else {
+        NSSize spacing = tableView.intercellSpacing ();
+        fullRect.width = rect.width + spacing.width;
+    }
+
+    if (hooks (DWT.EraseItem)) {
+        NSRect eraseItemRect = null;
+        // TODO how to handle rearranged columns?  The third clause below ensures that
+        // there are either 0 columns or that column 0 is still the first physical column.
+        if (columnIndex is 0 && (style & DWT.CHECK) !is 0 && (columnCount is 0 || tableView.columnWithIdentifier (columns[0].nsColumn) is 1)) {
+            eraseItemRect = new NSRect ();
+            eraseItemRect.y = fullRect.y;
+            eraseItemRect.width = fullRect.x + fullRect.width;
+            eraseItemRect.height = fullRect.height;
+        } else {
+            eraseItemRect = fullRect;
+        }
+        GCData data = new GCData ();
+        data.paintRect = eraseItemRect;
+        GC gc = GC.cocoa_new (this, data);
+        gc.setFont (item.getFont (columnIndex));
+        if (isSelected) {
+            float /*double*/[] components = new float /*double*/[(int)/*64*/nsSelectionForeground.numberOfComponents ()];
+            nsSelectionForeground.getComponents (components);   
+            Color selectionForeground = Color.cocoa_new (display, components);
+            gc.setForeground (selectionForeground);
+            components = new float /*double*/[(int)/*64*/nsSelectionBackground.numberOfComponents ()];
+            nsSelectionBackground.getComponents (components);   
+            Color selectionBackground = Color.cocoa_new (display, components);
+            gc.setBackground (selectionBackground);
+        } else {
+            gc.setForeground (item.getForeground (columnIndex));
+            gc.setBackground (item.getBackground (columnIndex));
+        }
+
+        Event event = new Event ();
+        event.item = item;
+        event.gc = gc;
+        event.index = columnIndex;
+        event.detail = DWT.FOREGROUND;
+        if (drawBackground) event.detail |= DWT.BACKGROUND;
+        if (isSelected) event.detail |= DWT.SELECTED;
+        event.x = (int)eraseItemRect.x;
+        event.y = (int)eraseItemRect.y;
+        event.width = (int)eraseItemRect.width;
+        event.height = (int)eraseItemRect.height;
+        sendEvent (DWT.EraseItem, event);
+        gc.dispose ();
+        if (item.isDisposed ()) return;
+        if (!event.doit) {
+            drawForeground = drawBackground = drawSelection = false; 
+        } else {
+            drawBackground = drawBackground && (event.detail & DWT.BACKGROUND) !is 0;
+            drawForeground = (event.detail & DWT.FOREGROUND) !is 0;
+            drawSelection = drawSelection && (event.detail & DWT.SELECTED) !is 0;           
+        }
+
+        if (drawSelection) {
+            NSRect selectionRect = new NSRect ();
+            selectionRect.y = rect.y; selectionRect.height = rect.height;
+            if (columnCount > 0) {
+                NSRect columnRect = tableView.rectOfColumn (nsColumnIndex);
+                selectionRect.x = columnRect.x; selectionRect.width = columnRect.width;
+            } else {
+                NSRect rowRect = tableView.rectOfRow (rowIndex);
+                if ((style & DWT.CHECK) !is 0) {
+                    /* highlighting at this stage draws over the checkbox, so don't include its column */
+                    int checkWidth = (int)/*64*/checkColumn.width ();
+                    selectionRect.x = checkWidth;
+                    selectionRect.width = rowRect.width - checkWidth;
+                } else {
+                    selectionRect.width = rowRect.width;
+                }
+            }
+            callSuper (tableView.id, OS.sel_highlightSelectionInClipRect_, selectionRect);
+        }   
+    }
+
+    if (drawBackground && !drawSelection) {
+        NSGraphicsContext context = NSGraphicsContext.currentContext ();
+        context.saveGraphicsState ();
+        float[] colorRGB = background.handle;
+        NSColor color = NSColor.colorWithDeviceRed (colorRGB[0], colorRGB[1], colorRGB[2], 1f);
+        color.setFill ();
+        NSBezierPath.fillRect (fullRect);
+        context.restoreGraphicsState ();
+    }
+
+    if (drawForeground) {
+        cell.setHighlighted (false);
+        callSuper (id, sel, rect, view);
+    }
+
+    if (hooks (DWT.PaintItem)) {
+        NSRect contentRect = cell.titleRectForBounds (rect);
+        NSSize contentSize = cell.cellSizeForBounds (rect);
+
+        GCData data = new GCData ();
+        // TODO how to handle rearranged columns?  The third clause below ensures that
+        // there are either 0 columns or that column 0 is still the first physical column.
+        if (columnIndex is 0 && (style & DWT.CHECK) !is 0 && (columnCount is 0 || tableView.columnWithIdentifier (columns[0].nsColumn) is 1)) {
+            NSRect gcRect = new NSRect ();
+            gcRect.y = fullRect.y;
+            gcRect.width = fullRect.x + fullRect.width;
+            gcRect.height = fullRect.height;
+            data.paintRect = gcRect;
+        } else {
+            data.paintRect = fullRect;
+        }
+        GC gc = GC.cocoa_new (this, data);
+        gc.setFont (item.getFont (columnIndex));
+        if (isSelected) {
+            float /*double*/[] components = new float /*double*/[(int)/*64*/nsSelectionForeground.numberOfComponents ()];
+            nsSelectionForeground.getComponents (components);   
+            Color selectionForeground = Color.cocoa_new (display, components);
+            gc.setForeground (selectionForeground);
+            components = new float /*double*/[(int)/*64*/nsSelectionBackground.numberOfComponents ()];
+            nsSelectionBackground.getComponents (components);   
+            Color selectionBackground = Color.cocoa_new (display, components);
+            gc.setBackground (selectionBackground);
+            gc.setBackground (display.getSystemColor (DWT.COLOR_GREEN));
+        } else {
+            gc.setForeground (item.getForeground (columnIndex));
+            gc.setBackground (item.getBackground (columnIndex));
+        }
+
+        Event event = new Event ();
+        event.item = item;
+        event.gc = gc;
+        event.index = columnIndex;
+        if (isSelected) event.detail |= DWT.SELECTED;
+        event.x = (int)contentRect.x;
+        event.y = (int)contentRect.y;
+        event.width = (int)Math.ceil (contentSize.width);
+        event.height = (int)Math.ceil (fullRect.height);
+        sendEvent (DWT.PaintItem, event);
+        gc.dispose ();
+    }
+}
+
 void fixSelection (int index, bool add) {
     int [] selection = getSelectionIndices ();
     if (selection.length is 0) return;
@@ -756,6 +1013,15 @@
     return 20; //TODO - compute width
 }
 
+TableColumn getColumn (id id) {
+    for (int i = 0; i < columnCount; i++) {
+        if (columns[i].nsColumn.id is id.id) {
+            return columns[i]; 
+        }
+    }
+    return null;
+}
+
 /**
  * Returns the column at the given, zero-relative index in the
  * receiver. Throws an exception if the index is out of range.
@@ -839,12 +1105,11 @@
 public int [] getColumnOrder () {
     checkWidget ();
     int [] order = new int [columnCount];
-    int [] position = new int [1];
-    for (int i=0; i<columnCount; i++) {
+    for (int i = 0; i < columnCount; i++) {
         TableColumn column = columns [i];
-//      OS.GetDataBrowserTableViewColumnPosition (handle, column.id, position);
-//      if ((style & DWT.CHECK) !is 0) position [0] -= 1;
-        order [position [0]] = i;
+        int index = ((NSTableView)view).columnWithIdentifier (column.nsColumn);
+        if ((style & DWT.CHECK) !is 0) index -= 1;
+        order [index] = i;
     }
     return order;
 }
@@ -990,85 +1255,13 @@
  */
 public TableItem getItem (Point point) {
     checkWidget ();
-//  checkItems (true);
-//  if (point is null) error (DWT.ERROR_NULL_ARGUMENT);
-//  Rect rect = new Rect ();
-//  dwt.internal.carbon.Point pt = new dwt.internal.carbon.Point ();
-//  OS.SetPt (pt, cast(short) point.x, cast(short) point.y);
-//  if (0 < lastHittest && lastHittest <= itemCount && lastHittestColumn !is 0) {
-//      if (OS.GetDataBrowserItemPartBounds (handle, lastHittest, lastHittestColumn, OS.kDataBrowserPropertyEnclosingPart, rect) is OS.noErr) {
-//          if (rect.top <= pt.v && pt.v <= rect.bottom) {
-//              if ((style & DWT.FULL_SELECTION) !is 0) {
-//                  return _getItem (lastHittest - 1);
-//              } else {
-//                  return OS.PtInRect (pt, rect) ? _getItem (lastHittest - 1) : null;
-//              }
-//          }
-//      }
-//          
-//  }
-//  int [] top = new int [1], left = new int [1];
-//    OS.GetDataBrowserScrollPosition(handle, top, left);
-//  short [] height = new short [1];
-//  OS.GetDataBrowserTableViewRowHeight (handle, height);
-//  short [] header = new short [1];
-//  OS.GetDataBrowserListViewHeaderBtnHeight (handle, header);
-//  int [] offsets = new int [] {0, 1, -1};
-//  for (int i = 0; i < offsets.length; i++) {
-//      int index = (top[0] - header [0] + point.y) / height [0] + offsets [i];
-//      if (0 <= index && index < itemCount) {
-//          if (columnCount is 0) {
-//              if (OS.GetDataBrowserItemPartBounds (handle, index + 1, column_id, OS.kDataBrowserPropertyEnclosingPart, rect) is OS.noErr) {
-//                  if (rect.top <= pt.v && pt.v <= rect.bottom) {
-//                      if ((style & DWT.FULL_SELECTION) !is 0) {
-//                          return _getItem (index);
-//                      } else {
-//                          return OS.PtInRect (pt, rect) ? _getItem (index) : null;
-//                      }
-//                  }
-//              }
-//          } else {
-//              for (int j = 0; j < columnCount; j++) {
-//                  if (OS.GetDataBrowserItemPartBounds (handle, index + 1, columns [j].id, OS.kDataBrowserPropertyEnclosingPart, rect) is OS.noErr) {
-//                      if (rect.top <= pt.v && pt.v <= rect.bottom) {
-//                          if ((style & DWT.FULL_SELECTION) !is 0) {
-//                              return _getItem (index);
-//                          } else {
-//                              return OS.PtInRect (pt, rect) ? _getItem (index) : null;
-//                          }
-//                      }
-//                  }
-//              }
-//          }
-//      }
-//  }
-//  //TODO - optimize
-//  for (int i=0; i<itemCount; i++) {
-//      if (columnCount is 0) {
-//          if (OS.GetDataBrowserItemPartBounds (handle, i + 1, column_id, OS.kDataBrowserPropertyEnclosingPart, rect) is OS.noErr) {
-//              if (rect.top <= pt.v && pt.v <= rect.bottom) {
-//                  if ((style & DWT.FULL_SELECTION) !is 0) {
-//                      return _getItem (i);
-//                  } else {
-//                      return OS.PtInRect (pt, rect) ? _getItem (i) : null;
-//                  }
-//              }
-//          }
-//      } else {
-//          for (int j = 0; j < columnCount; j++) {
-//              if (OS.GetDataBrowserItemPartBounds (handle, i + 1, columns [j].id, OS.kDataBrowserPropertyEnclosingPart, rect) is OS.noErr) {
-//                  if (rect.top <= pt.v && pt.v <= rect.bottom) {
-//                      if ((style & DWT.FULL_SELECTION) !is 0) {
-//                          return _getItem (i);
-//                      } else {
-//                          return OS.PtInRect (pt, rect) ? _getItem (i) : null;
-//                      }
-//                  }
-//              }
-//          }
-//      }
-//  }
-    return null;
+    NSTableView widget = (NSTableView)view;
+    NSPoint pt = new NSPoint();
+    pt.x = point.x;
+    pt.y = point.y;
+    int row = cast(int)/*64*/widget.rowAtPoint(pt);
+    if (row is -1) return null;
+    return items[row];
 }
 
 /**
@@ -1088,7 +1281,7 @@
 
 /**
  * Returns the height of the area which would be used to
- * display <em>one</em> of the items in the receiver's.
+ * display <em>one</em> of the items in the receiver.
  *
  * @return the height of one item
  *
@@ -1150,12 +1343,7 @@
  */
 public bool getLinesVisible () {
     checkWidget ();
-//  if (OS.VERSION >= 0x1040) {
-//      int [] attrib = new int [1];
-//      OS.DataBrowserGetAttributes (handle, attrib);
-//      return (attrib [0] & (OS.kDataBrowserAttributeListViewAlternatingRowColors | OS.kDataBrowserAttributeListViewDrawColumnDividers)) !is 0;
-//  }
-    return false;
+    return ((NSTableView)view).usesAlternatingRowBackgroundColors();
 }
 
 /**
@@ -1181,12 +1369,12 @@
         return new TableItem [0];
     }
     NSIndexSet selection = widget.selectedRowIndexes();
-    int count = selection.count();
-    int [] indexBuffer = new int [count];
+    int count = (int)/*64*/selection.count();
+    int /*long*/ [] indexBuffer = new int /*long*/ [count];
     selection.getIndexes(indexBuffer, count, 0);
     TableItem [] result = new TableItem  [count];
     for (int i=0; i<count; i++) {
-        result [i] = _getItem (indexBuffer [i]);
+        result [i] = _getItem ((int)/*64*/indexBuffer [i]);
     }
     return result;
 }
@@ -1203,7 +1391,7 @@
  */
 public int getSelectionCount () {
     checkWidget ();
-    return (cast(NSTableView)view).numberOfSelectedRows();
+    return cast(int)/*64*/(cast(NSTableView)view).numberOfSelectedRows();
 }
 
 /**
@@ -1218,9 +1406,16 @@
  * </ul>
  */
 public int getSelectionIndex () {
-    checkWidget();
-    //TODO - check empty selection case
-    return (cast(NSTableView)view).selectedRow();
+    checkWidget ();
+    NSTableView widget = (NSTableView)view;
+    if (widget.numberOfSelectedRows() is 0) {
+        return -1;
+    }
+    NSIndexSet selection = widget.selectedRowIndexes();
+    int count = (int)/*64*/selection.count();
+    int /*long*/ [] result = new int /*long*/ [count];
+    selection.getIndexes(result, count, 0);
+    return (int)/*64*/result [0];
 }
 
 /**
@@ -1246,9 +1441,13 @@
         return new int [0];
     }
     NSIndexSet selection = widget.selectedRowIndexes();
-    int count = selection.count();
+    int count = (int)/*64*/selection.count();
+    int /*long*/ [] indices = new int /*long*/ [count];
+    selection.getIndexes(indices, count, 0);
     int [] result = new int [count];
-    selection.getIndexes(result, count, 0);
+    for (int i = 0; i < indices.length; i++) {
+        result [i] = (int)/*64*/indices [i];
+    }
     return result;
 }
 
@@ -1307,15 +1506,22 @@
  * </ul>
  */
 public int getTopIndex () {
-    checkWidget();
+    checkWidget ();
     //TODO - partial item at the top
     NSRect rect = scrollView.documentVisibleRect();
     NSPoint point = new NSPoint();
     point.x = rect.x;
     point.y = rect.y;
-    return (cast(NSTableView)view).rowAtPoint(point);
+    return csat(int)/*64*/(cast(NSTableView)view).rowAtPoint(point);
 }
 
+void highlightSelectionInClipRect(int /*long*/ id, int /*long*/ sel, int /*long*/ rect) {
+    if (!hooks (DWT.EraseItem)) {
+        NSRect clipRect = new NSRect ();
+        OS.memmove (clipRect, rect, NSRect.sizeof);
+        callSuper (id, sel, clipRect);
+    }
+}
 
 /**
  * Searches the receiver's list starting at the first column
@@ -1394,15 +1600,26 @@
  * </ul>
  */
 public bool isSelected (int index) {
-    checkWidget();
-    //TODO - range check
+    checkWidget ();
+    if (!(0 <= index && index < itemCount)) return false;
     return (cast(NSTableView)view).isRowSelected(index);
 }
 
-int numberOfRowsInTableView(int aTableView) {
+bool isTrim (NSView view) {
+    if (super.isTrim (view)) return true;
+    return view.id is headerView.id;
+}
+
+int /*long*/ numberOfRowsInTableView(int /*long*/ id, int /*long*/ sel, int /*long*/ aTableView) {
     return itemCount;
 }
 
+void register () {
+    super.register ();
+    display.addWidget (headerView, this);
+    display.addWidget (dataCell, this);
+}
+
 void releaseChildren (bool destroy) {
     if (items !is null) {
         for (int i=0; i<itemCount; i++) {
@@ -1433,6 +1650,8 @@
     firstColumn = null;
     if (checkColumn !is null) checkColumn.release();
     checkColumn = null;
+    if (dataCell !is null) dataCell.release();
+    dataCell = null;
 }
 
 void releaseWidget () { 
@@ -1456,7 +1675,7 @@
  * </ul>
  */
 public void remove (int index) {
-    checkWidget();
+    checkWidget ();
     if (!(0 <= index && index < itemCount)) error (DWT.ERROR_INVALID_RANGE);
     TableItem item = items [index];
     if (item !is null) item.release (false);
@@ -1488,7 +1707,7 @@
  * </ul>
  */
 public void remove (int start, int end) {
-    checkWidget();
+    checkWidget ();
     if (start > end) return;
     if (!(0 <= start && start <= end && end < itemCount)) {
         error (DWT.ERROR_INVALID_RANGE);
@@ -1546,7 +1765,7 @@
  * </ul>
  */
 public void removeAll () {
-    checkWidget();
+    checkWidget ();
     for (int i=0; i<itemCount; i++) {
         TableItem item = items [i];
         if (item !is null && !item.isDisposed ()) item.release (false);
@@ -1593,13 +1812,13 @@
  * </ul>
  */
 public void select (int index) {
-    checkWidget();
+    checkWidget ();
     if (0 <= index && index < itemCount) {
         NSIndexSet indexes = cast(NSIndexSet)new NSIndexSet().alloc();
         indexes.initWithIndex(index);
         NSTableView widget = cast(NSTableView)view;
         ignoreSelect = true;
-        (cast(NSTableView)view).selectRowIndexes(indexes, true);
+        widget.selectRowIndexes(indexes, (style & DWT.MULTI) !is 0);
         ignoreSelect = false;
     }
 }
@@ -1644,7 +1863,7 @@
         indexes.initWithIndexesInRange(range);
         NSTableView widget = cast(NSTableView)view;
         ignoreSelect = true;
-        widget.selectRowIndexes(indexes, true);
+        widget.selectRowIndexes(indexes, (style & DWT.MULTI) !is 0);
         ignoreSelect = false;
     }
 }
@@ -1680,7 +1899,7 @@
     int count = 0;
     NSMutableIndexSet indexes = cast(NSMutableIndexSet)new NSMutableIndexSet().alloc().init();
     for (int i=0; i<length; i++) {
-        int index = indices [length - i - 1];
+        int index = indices [i];
         if (index >= 0 && index < itemCount) {
             indexes.addIndex (indices [i]);
             count++;
@@ -1689,7 +1908,7 @@
     if (count > 0) {
         NSTableView widget = cast(NSTableView)view;
         ignoreSelect = true;
-        widget.selectRowIndexes(indexes, true);
+        widget.selectRowIndexes(indexes, (style & DWT.MULTI) !is 0);
         ignoreSelect = false;
     }
 }
@@ -1723,6 +1942,17 @@
     ignoreSelect = false;
 }
 
+void setBackground (float [] color) {
+    super.setBackground (color);
+    NSColor nsColor;
+    if (color is null) {
+        nsColor = null;
+    } else {
+        nsColor = NSColor.colorWithDeviceRed (color [0], color [1], color [2], 1);
+    }
+    ((NSTableView) view).setBackgroundColor (nsColor);
+}
+
 /**
  * Sets the order that the items in the receiver should 
  * be displayed in to the given argument which is described
@@ -1766,27 +1996,21 @@
         if (order [i] !is oldOrder [i]) reorder = true;
     }
     if (reorder) {
-        int x = 0;
-        short [] width = new short [1];
+        NSTableView tableView = (NSTableView)view;
         int [] oldX = new int [oldOrder.length];
+        int check = (style & DWT.CHECK) !is 0 ? 1 : 0;
         for (int i=0; i<oldOrder.length; i++) {
-            int index = oldOrder [i];
-            TableColumn column = columns [index];
-            oldX [index] =  x;
-//          OS.GetDataBrowserTableViewNamedColumnWidth(handle, column.id, width);
-            x += width [0];
+            int index = oldOrder[i];
+            oldX [index] = (int)tableView.rectOfColumn (i + check).x;
         }
-        x = 0;
         int [] newX = new int [order.length];
         for (int i=0; i<order.length; i++) {
             int index = order [i];
-            TableColumn column = columns [index];
-            int position = (style & DWT.CHECK) !is 0 ? i + 1 : i;
-//          OS.SetDataBrowserTableViewColumnPosition(handle, column.id, position);
-//          column.lastPosition = position;
-            newX [index] =  x;
-//          OS.GetDataBrowserTableViewNamedColumnWidth(handle, column.id, width);
-            x += width [0];
+            TableColumn column = columns[index];
+            int oldIndex = tableView.columnWithIdentifier (column.nsColumn);
+            int newIndex = i + check;
+            tableView.moveColumn (oldIndex, newIndex);
+            newX [index] = (int)tableView.rectOfColumn (newIndex).x;
         }
         TableColumn[] newColumns = new TableColumn [columnCount];
         System.arraycopy (columns, 0, newColumns, 0, columnCount);
@@ -1801,6 +2025,17 @@
     }
 }
 
+void setFont(NSFont font) {
+    super.setFont (font);
+    if (!hooks (DWT.MeasureItem)) {
+        float ascent = font.ascender ();
+        float descent = -font.descender () + font.leading ();
+        ((NSTableView)view).setRowHeight ((int)Math.ceil (ascent + descent) + 1);
+    } else {
+        view.setNeedsDisplay (true);
+    }
+}
+
 /**
  * Marks the receiver's header as visible if the argument is <code>true</code>,
  * and marks it invisible otherwise. 
@@ -1836,49 +2071,33 @@
  */
 public void setItemCount (int count) {
     checkWidget ();
-//  checkItems (true);
-//  count = Math.max (0, count);
-//  if (count is itemCount) return;
-//  setRedraw (false);
-//    int[] top = new int [1], left = new int [1];
-//    OS.GetDataBrowserScrollPosition (handle, top, left);
-//    DataBrowserCallbacks callbacks = new DataBrowserCallbacks ();
-//  OS.GetDataBrowserCallbacks (handle, callbacks);
-//  callbacks.v1_itemNotificationCallback = 0;
-//  callbacks.v1_itemCompareCallback = 0;
-//  OS.SetDataBrowserCallbacks (handle, callbacks);
-//  if (count < itemCount) {
-//      int index = count;
-//      int[] id = new int [itemCount - count];
-//      while (index < itemCount) {
-//          TableItem item = items [index];
-//          if (item !is null) item.release (false);
-//          id [index-count] = index + 1;
-//          index++;
-//      }
-//      OS.RemoveDataBrowserItems (handle, OS.kDataBrowserNoItem, id.length, id, 0);
-//      int [] newItemCount = new int [1];
-//      if (OS.GetDataBrowserItemCount (handle, OS.kDataBrowserNoItem, true, OS.kDataBrowserItemAnyState, newItemCount) !is OS.noErr) {
-//          error (DWT.ERROR_CANNOT_GET_COUNT);
-//      }
-//      if (count !is newItemCount[0]) error (DWT.ERROR_ITEM_NOT_REMOVED);
-//  }
-//  int length = Math.max (4, (count + 3) / 4 * 4);
-//  TableItem [] newItems = new TableItem [length];
-//  System.arraycopy (items, 0, newItems, 0, Math.min (count, itemCount));
-//  items = newItems;
-//  if ((style & DWT.VIRTUAL) is 0) {
-//      for (int i=itemCount; i<count; i++) {
-//          items [i] = new TableItem (this, DWT.NONE, i, false);
-//      }
-//  }
-//  itemCount = count;
-//  OS.AddDataBrowserItems (handle, 0, itemCount, null, OS.kDataBrowserItemNoProperty);
-//  callbacks.v1_itemNotificationCallback = display.itemNotificationProc;
-//  callbacks.v1_itemCompareCallback = itemCompareProc ();
-//  OS.SetDataBrowserCallbacks (handle, callbacks);
-//  fixScrollBar ();
-//  setRedraw (true);
+    count = Math.max (0, count);
+    if (count is itemCount) return;
+    if (count is itemCount) return;
+    TableItem [] children = items;
+    if (count < itemCount) {
+        for (int index = count; index < itemCount; index ++) {
+            TableItem item = children [index];
+            if (item !is null && !item.isDisposed()) item.release (false);
+        }
+    }
+    if (count > itemCount) {
+        if ((getStyle() & DWT.VIRTUAL) is 0) {
+            for (int i=itemCount; i<count; i++) {
+                new TableItem (this, DWT.NONE, i, true);
+            }
+            return;
+        } 
+    }
+    int length = Math.max (4, (count + 3) / 4 * 4);
+    TableItem [] newItems = new TableItem [length];
+    if (children !is null) {
+        System.arraycopy (items, 0, children, 0, Math.min (count, itemCount));
+    }
+    children = newItems;
+    this.items = newItems;
+    this.itemCount = count;
+    ((NSTableView) view).noteNumberOfRowsChanged ();
 }
 
 /*public*/ void setItemHeight (int itemHeight) {
@@ -1891,6 +2110,14 @@
     }
 }
 
+public void setRedraw (bool redraw) {
+    checkWidget ();
+    super.setRedraw (redraw);
+    if (redraw && drawCount is 0) {
+        setScrollWidth ();
+    }
+}
+
 /**
  * Marks the receiver's lines as visible if the argument is <code>true</code>,
  * and marks it invisible otherwise. 
@@ -1912,57 +2139,44 @@
     (cast(NSTableView)view).setUsesAlternatingRowBackgroundColors(show);
 }
 
-bool setScrollWidth (TableItem item) {
+bool setScrollWidth () {
+    return setScrollWidth (items, true);
+}
+
+bool setScrollWidth (TableItem item, bool callMeasureItem) {
+    return setScrollWidth (new TableItem[] {item}, callMeasureItem);
+}
+
+bool setScrollWidth (TableItem items[], bool callMeasureItem) {
     if (columnCount !is 0) return false;
     if (currentItem !is null) {
 //      if (currentItem !is item) fixScrollWidth = true;
         return false;
     }
-    if (drawCount !is 0) return false;
+    if (/*ignoreRedraw ||*/ drawCount !is 0) return false;
+    int newWidth = 0;
     GC gc = new GC (this);
-    int newWidth = item.calculateWidth (0, gc);
-    gc.dispose ();
-    newWidth += getInsetWidth ();
-//  short [] width = new short [1];
-//  OS.GetDataBrowserTableViewNamedColumnWidth (handle, column_id, width);
-//  if (width [0] < newWidth) {
-//      OS.SetDataBrowserTableViewNamedColumnWidth (handle, column_id, cast(short) newWidth);
-//      return true;
-//  }
-    if (firstColumn.width() < newWidth) {
-        firstColumn.setWidth (newWidth);
-    }
-    return false;
-}
-
-bool setScrollWidth (TableItem [] items, bool set) {
-    if (columnCount !is 0) return false;
-    if (currentItem !is null) {
-//      fixScrollWidth = true;
-        return false;
-    }
-    if (drawCount !is 0) return false;
-    GC gc = new GC (this);
-    int newWidth = 0;
     for (int i = 0; i < items.length; i++) {
-        TableItem item = items [i];
-        if (item !is null) {
-            newWidth = Math.max (newWidth, item.calculateWidth (0, gc));
+        TableItem item = items[i];
+        if (item !is null && !item.isDisposed ()) {
+            newWidth = Math.max (newWidth, item.calculateWidth (0, gc, callMeasureItem));
+            if (isDisposed ()) {
+                gc.dispose ();
+                return false;
+            }
         }
     }
     gc.dispose ();
     newWidth += getInsetWidth ();
-//  if (!set) {
-//      short [] width = new short [1];
-//      OS.GetDataBrowserTableViewNamedColumnWidth (handle, column_id, width);
-//      if (width [0] >= newWidth) return false;
-//  }
-//  OS.SetDataBrowserTableViewNamedColumnWidth (handle, column_id, cast(short) newWidth);
-    if (!set) {
-        if (firstColumn.width() > newWidth) return false;
+    if (firstColumn.width () < newWidth) {
+        NSTableView tableView = (NSTableView)view;
+        int /*long*/ oldResize = tableView.columnAutoresizingStyle ();
+        tableView.setColumnAutoresizingStyle (OS.NSTableViewNoColumnAutoresizing);
+        firstColumn.setWidth (newWidth);
+        tableView.setColumnAutoresizingStyle (oldResize);
+        return true;
     }
-    firstColumn.setWidth (newWidth);
-    return true;
+    return false;
 }
 
 /**
@@ -1980,14 +2194,14 @@
  * @see Table#select(int)
  */
 public void setSelection (int index) {
-    checkWidget();
+    checkWidget ();
     //TODO - optimize to use expand flag
     deselectAll ();
     setSelection (index, false);
 }
 
 void setSelection (int index, bool notify) {
-//  checkWidget();
+//  checkWidget ();
     if (0 <= index && index < itemCount) {
         select (index);
         showIndex (index);
@@ -2158,25 +2372,21 @@
     checkWidget ();
     if (column !is null && column.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
     if (column is sortColumn) return;
-//  DataBrowserCallbacks callbacks = new DataBrowserCallbacks ();
-//  OS.GetDataBrowserCallbacks (handle, callbacks);
-//  callbacks.v1_itemCompareCallback = display.itemCompareProc;
-//  OS.SetDataBrowserCallbacks (handle, callbacks);
-//  if (column is null) {
-//      if (sortColumn !is null  && !sortColumn.isDisposed ()  && sortDirection !is DWT.NONE) {
-//          OS.SetDataBrowserSortOrder (handle, cast(short) OS.kDataBrowserOrderIncreasing);
-//          sortColumn = null; 
-//          OS.SetDataBrowserSortProperty (handle, 0);
-//      }
-//  }
-//  sortColumn = column;
-//  if (sortColumn !is null  && !sortColumn.isDisposed () && sortDirection !is DWT.NONE) {
-//      OS.SetDataBrowserSortProperty (handle, sortColumn.id);
-//      int order = sortDirection is DWT.DOWN ? OS.kDataBrowserOrderDecreasing : OS.kDataBrowserOrderIncreasing;
-//      OS.SetDataBrowserSortOrder (handle, cast(short) order);
-//  }
-//  callbacks.v1_itemCompareCallback = itemCompareProc ();
-//  OS.SetDataBrowserCallbacks (handle, callbacks);
+    TableColumn oldSortColumn = sortColumn;
+    sortColumn = column;
+    if (sortDirection is DWT.NONE) return;
+    NSTableHeaderView headerView = ((NSTableView)view).headerView ();
+    if (headerView is null) return;
+    if (oldSortColumn !is null) {
+        NSInteger index = ((NSTableView)view).columnWithIdentifier (oldSortColumn.nsColumn);
+        NSRect rect = headerView.headerRectOfColumn (index);
+        headerView.setNeedsDisplayInRect (rect);
+    }
+    if (sortColumn !is null) {
+        int /*long*/ index = ((NSTableView)view).columnWithIdentifier (sortColumn.nsColumn);
+        NSRect rect = headerView.headerRectOfColumn (index);
+        headerView.setNeedsDisplayInRect (rect);
+    }
 }
 
 /**
@@ -2197,26 +2407,12 @@
     if (direction !is DWT.UP && direction !is DWT.DOWN && direction !is DWT.NONE) return;
     if (direction is sortDirection) return;
     sortDirection = direction;
-//  DataBrowserCallbacks callbacks = new DataBrowserCallbacks ();
-//  OS.GetDataBrowserCallbacks (handle, callbacks);
-//  callbacks.v1_itemCompareCallback = display.itemCompareProc;
-//  OS.SetDataBrowserCallbacks (handle, callbacks);
-//  if (sortColumn !is null && !sortColumn.isDisposed ()) {
-//      if (sortDirection is DWT.NONE) {
-//          OS.SetDataBrowserSortOrder (handle, cast(short) OS.kDataBrowserOrderIncreasing);
-//          TableColumn column = sortColumn;
-//          sortColumn = null; 
-//          OS.SetDataBrowserSortProperty (handle, 0);
-//          sortColumn = column;
-//      } else {
-//          OS.SetDataBrowserSortProperty (handle, 0);
-//          OS.SetDataBrowserSortProperty (handle, sortColumn.id);
-//          int order = sortDirection is DWT.DOWN ? OS.kDataBrowserOrderDecreasing : OS.kDataBrowserOrderIncreasing;
-//          OS.SetDataBrowserSortOrder (handle, cast(short) order);
-//      }
-//  }
-//  callbacks.v1_itemCompareCallback = itemCompareProc ();
-//  OS.SetDataBrowserCallbacks (handle, callbacks);
+    if (sortColumn is null) return;
+    NSTableHeaderView headerView = ((NSTableView)view).headerView ();
+    if (headerView is null) return;
+    int /*long*/ index = ((NSTableView)view).columnWithIdentifier (sortColumn.nsColumn);
+    NSRect rect = headerView.headerRectOfColumn (index);
+    headerView.setNeedsDisplayInRect (rect);
 }
 
 void setTableEmpty () {
@@ -2237,7 +2433,7 @@
  * </ul>
  */
 public void setTopIndex (int index) {
-    checkWidget();
+    checkWidget ();
     NSRect rect = (cast(NSTableView)view).rectOfRow(index);
     (cast(NSTableView)view).scrollRectToVisible(rect);
 }
@@ -2265,9 +2461,10 @@
     if (column is null) error (DWT.ERROR_NULL_ARGUMENT);
     if (column.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT);
     if (column.parent !is this) return;
-    int index = indexOf (column);
-    if (columnCount <= 1 || !(0 <= index && index < columnCount)) return;
-    (cast(NSTableView)view).scrollColumnToVisible(index + ((style & DWT.CHECK) !is 0 ? 1 : 0));
+    if (columnCount <= 1) return;
+    int index = (int)/*64*/((NSTableView)view).columnWithIdentifier (column.nsColumn);
+    if (!(0 <= index && index < columnCount + ((style & DWT.CHECK) !is 0 ? 1 : 0))) return;
+    ((NSTableView)view).scrollColumnToVisible (index);
 }
 
 void showIndex (int index) {
@@ -2315,7 +2512,7 @@
  * @see Table#showItem(TableItem)
  */
 public void showSelection () {
-    checkWidget();
+    checkWidget ();
     int index = getSelectionIndex ();
     if (index >= 0) showIndex (index);
 }
@@ -2324,67 +2521,175 @@
     postEvent (DWT.DefaultSelection);
 }
 
-void tableViewSelectionDidChange (int aNotification) {
-    if (ignoreSelect) return;
-    NSTableView widget = cast(NSTableView)view;
-    int row = widget.selectedRow();
-    if(row is -1)
-        postEvent(DWT.Selection);
-    else {
-        TableItem item = _getItem(row);
-        Event event = new Event();
-        event.item = item;
-        event.index = row;
-        postEvent(DWT.Selection, event);
+bool sendKeyEvent (NSEvent nsEvent, int type) {
+    bool result = super.sendKeyEvent (nsEvent, type);
+    if (!result) return result;
+    if (type !is DWT.KeyDown) return result;
+    short keyCode = nsEvent.keyCode ();
+    switch (keyCode) {
+        case 76: /* KP Enter */
+        case 36: { /* Return */
+            postEvent (DWT.DefaultSelection);
+            break;
+        }
+    }
+    return result;
+}
+
+void tableViewColumnDidMove (int /*long*/ id, int /*long*/ sel, int /*long*/ aNotification) {
+    NSNotification notification = new NSNotification (aNotification);
+    NSDictionary userInfo = notification.userInfo ();
+    id nsOldIndex = userInfo.valueForKey (NSString.stringWith ("NSOldColumn")); //$NON-NLS-1$
+    id nsNewIndex = userInfo.valueForKey (NSString.stringWith ("NSNewColumn")); //$NON-NLS-1$
+    int oldIndex = new NSNumber (nsOldIndex).intValue ();
+    int newIndex = new NSNumber (nsNewIndex).intValue ();
+    int startIndex = Math.min (oldIndex, newIndex);
+    int endIndex = Math.max (oldIndex, newIndex);
+    NSTableView tableView = (NSTableView)view;
+    NSArray nsColumns = tableView.tableColumns ();
+    for (int i = startIndex; i <= endIndex; i++) {
+        id columnId = nsColumns.objectAtIndex (i);
+        TableColumn column = getColumn (columnId);
+        if (column !is null) {
+            column.sendEvent (DWT.Move);
+            if (isDisposed ()) return;
+        }
     }
 }
 
-int tableView_objectValueForTableColumn_row(int aTableView, int aTableColumn, int rowIndex) {
-    TableItem item = items [rowIndex];
+void tableViewColumnDidResize (int /*long*/ id, int /*long*/ sel, int /*long*/ aNotification) {
+    NSNotification notification = new NSNotification (aNotification);
+    NSDictionary userInfo = notification.userInfo ();
+    id columnId = userInfo.valueForKey (NSString.stringWith ("NSTableColumn")); //$NON-NLS-1$
+    TableColumn column = getColumn (columnId);
+    if (column is null) return; /* either CHECK column or firstColumn in 0-column Table */
+
+    column.sendEvent (DWT.Resize);
+    if (isDisposed ()) return;
+
+    NSTableView tableView = (NSTableView)view;
+    int index = (int)/*64*/tableView.columnWithIdentifier (columnId);
+    if (index is -1) return; /* column was disposed in Resize callback */
+
+    NSArray nsColumns = tableView.tableColumns ();
+    int columnCount = (int)/*64*/tableView.numberOfColumns ();
+    for (int i = index + 1; i < columnCount; i++) {
+        columnId = nsColumns.objectAtIndex (i);
+        column = getColumn (columnId);
+        if (column !is null) {
+            column.sendEvent (DWT.Move);
+            if (isDisposed ()) return;
+        }
+    }
+}
+
+void tableViewSelectionDidChange (int /*long*/ id, int /*long*/ sel, int /*long*/ aNotification) {
+    if (ignoreSelect) return;
+    NSTableView widget = cast(NSTableView) view;
+    int row = (int)/*64*/widget.selectedRow ();
+    if(row is -1)
+        postEvent (DWT.Selection);
+    else {
+        TableItem item = _getItem (row);
+        Event event = new Event ();
+        event.item = item;
+        event.index = row;
+        postEvent (DWT.Selection, event);
+    }
+}
+
+void tableView_didClickTableColumn (int /*long*/ id, int /*long*/ sel, int /*long*/ tableView, int /*long*/ tableColumn) {
+    TableColumn column = getColumn (new id (tableColumn));
+    column.postEvent (DWT.Selection);
+}
+
+int /*long*/ tableView_objectValueForTableColumn_row (int /*long*/ id, int /*long*/ sel, int /*long*/ aTableView, int /*long*/ aTableColumn, int /*long*/ rowIndex) {
+    TableItem item = _getItem ((int)/*64*/rowIndex);
     if (checkColumn !is null && aTableColumn is checkColumn.id) {
         NSNumber value;
         if (item.checked && item.grayed) {
-            value = NSNumber.numberWithInt(OS.NSMixedState);
+            value = NSNumber.numberWithInt (OS.NSMixedState);
         } else {
-            value = NSNumber.numberWithInt(item.checked ? OS.NSOnState : OS.NSOffState);
+            value = NSNumber.numberWithInt (item.checked ? OS.NSOnState : OS.NSOffState);
         }
         return value.id;
     }
     for (int i=0; i<columnCount; i++) {
         if (columns [i].nsColumn.id is aTableColumn) {
-            return item.createString(i).id;
+            return item.createString (i).id;
         }
     }
-    return item.createString(0).id;
+    return item.createString (0).id;
 }
 
-void tableView_setObjectValue_forTableColumn_row(int aTableView, int anObject, int aTableColumn, int rowIndex) {
-    TableItem item = items [rowIndex];
+void tableView_setObjectValue_forTableColumn_row (int /*long*/ id, int /*long*/ sel, int /*long*/ aTableView, int /*long*/ anObject, int /*long*/ aTableColumn, int /*long*/ rowIndex) {
     if (checkColumn !is null && aTableColumn is checkColumn.id)  {
+        TableItem item = items [(int)/*64*/rowIndex];
         item.checked = !item.checked;
-        Event event = new Event();
+        Event event = new Event ();
         event.detail = DWT.CHECK;
         event.item = item;
-        event.index = rowIndex;
-        postEvent(DWT.Selection, event);
+        event.index = (int)/*64*/rowIndex;
+        postEvent (DWT.Selection, event);
+        NSTableView tableView = (NSTableView)view;
+        NSRect rect = tableView.rectOfRow (rowIndex);
+        tableView.setNeedsDisplayInRect (rect);
     }
 }
 
-bool tableView_shouldEditTableColumn_row(int aTableView, int aTableColumn, int rowIndex) {
+bool tableView_shouldEditTableColumn_row (int /*long*/ id, int /*long*/ sel, int /*long*/ aTableView, int /*long*/ aTableColumn, int /*long*/ rowIndex) {
     return false;
 }
 
-void tableView_willDisplayCell_forTableColumn_row(int aTableView, int aCell, int aTableColumn, int rowIndex) {
+void tableView_willDisplayCell_forTableColumn_row (int /*long*/ id, int /*long*/ sel, int /*long*/ aTableView, int /*long*/ aCell, int /*long*/ aTableColumn, int /*long*/ rowIndex) {
     if (checkColumn !is null && aTableColumn is checkColumn.id) return;
-    TableItem item = items [rowIndex];
+    TableItem item = items [(int)/*64*/rowIndex];
     Image image = item.image;
+    int columnIndex = 0;
     for (int i=0; i<columnCount; i++) {
         if (columns [i].nsColumn.id is aTableColumn) {
-            image = item.getImage(i);
+            image = item.getImage (i);
+            columnIndex = i;
         }
     }
-    NSBrowserCell cell = new NSBrowserCell(aCell);
-    cell.setImage(image !is null ? image.handle : null);
-    cell.setLeaf(true);
+    NSBrowserCell cell = new NSBrowserCell (aCell);
+    cell.setFont (item.getFont (columnIndex).handle);
+    cell.setImage (image !is null ? image.handle : null);
+    cell.setLeaf (true);
+
+    if (hooks (DWT.MeasureItem)) {
+        NSTableView tableView = (NSTableView)this.view;
+        int nsColumnIndex = (int)/*64*/tableView.columnWithIdentifier (new id (aTableColumn));
+        NSRect rect = tableView.frameOfCellAtColumn (nsColumnIndex, rowIndex);
+        NSRect contentRect = cell.titleRectForBounds (rect);
+        NSSize contentSize = cell.cellSizeForBounds (rect);
+
+        GCData data = new GCData ();
+        data.paintRect = tableView.frame ();
+        GC gc = GC.cocoa_new (this, data);
+        gc.setFont (item.getFont (columnIndex));
+        int rowHeight = (int)tableView.rowHeight ();
+        Event event = new Event ();
+        event.item = item;
+        event.gc = gc;
+        event.index = columnIndex;
+        event.x = (int)contentRect.x;
+        event.y = (int)contentRect.y;
+        event.width = (int)Math.ceil (contentSize.width);
+        event.height = rowHeight;
+        sendEvent (DWT.MeasureItem, event);
+        gc.dispose ();
+        if (isDisposed ()) return;
+        if (rowHeight < event.height) {
+            tableView.setRowHeight(event.height);
+        }
+        if (columnCount is 0) {
+            int change = event.width - (item.customWidth !is -1 ? item.customWidth : (int)Math.ceil (contentSize.width));
+            if (item.customWidth !is -1 || event.width !is (int)Math.ceil (contentSize.width)) {
+                item.customWidth = event.width; 
+            }
+            if (change !is 0) setScrollWidth (item, false);
+        }
+    }
 }
 }