views:

110

answers:

1

What would be the easiest or recommended way for making an NSOutlineView indent multiple columns? By default, it only indents the outline column; and as far as I know there is no built-in support for making it indent other columns.

I have an NSOutlineView which shows a comparison between two sets of hierarchical data. For visual appeal, if some item in the outline column is indented, I'd like to indent the item on the same row in another column by the same indentation amount. (There's also a third column which shows the result of comparing the two items, this column should never be indented.)

Can this only be achieved by subclassing NSOutlineView? And what would need to be overridden in the subclass? Or is there an easier way to get it to indent multiple columns?

+1  A: 

Turns out to be easier than I expected. Here's a sketch of the solution. To indent a column other than the outline column in an NSOutlineView, you can:

  • Create a subclass of the NSCell class you will be using for that column, say MYIndentedCell
  • Add an instance variable indentation to MYIndentedCell, and provide an accessor and mutator method for it
  • Override at least drawWithFrame:inView: in MYIndentedCell to:
     - (void) drawWithFrame: (NSRect) frame inView: (NSView*) view
     {
       NSRect newFrame = frame;
       newFrame.origin.x += indentation;
       newFrame.size.width -= indentation;
       [super drawWithFrame: newFrame inView: view];
     }
  • You will need to also override editWithFrame:inView and selectWithFrame:inView: similar to the above if the column will be editable
  • Override cellSize to:
     - (NSSize) cellSize
     {
       NSSize cellSize = [super cellSize];
       cellSize.width += indentation;
       return cellSize;
     }
  • Finally, getting the indentation in the column to follow the indentation of the NSOutlineView's outline column will be handled by the outline view's delegate. The delegate needs to implement the following:
     - (void) outlineView: (NSOutlineView *) view
              willDisplayCell: (id) cell
              forTableColumn: (NSTableColumn *) column
              item: (id) item
     {
       if (column == theColumnToBeIndented) {
         [cell setIndentation:
                  [view indentationPerLevel] * [view levelForItem: item]];
       }
     }

If you're still having trouble getting it to work, you might want to take a look at ImageAndTextCell.m in Apple's SourceView sample code which I found very helpful in figuring out how to do the above.

Rinzwind