View-based NSTableView question

  • Hey guys,

    I'm trying to replace my old cell-based NSTableView system with the new 10.7+ view-based one without using Xcode's Interface Builder for the table view and column creation.
    What I am doing now is creating an NSTableCellView inside NSTableView's delegate method [-NSTableView tableView:viewForTableColumn:row:]:

    - (NSView *)tableView:(NSOutlineView *)aTableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
    {
    NSString *identifier = [tableColumn identifier];
    NSString *stringValue = [self tableView:aTableView objectValueForTableColumn:tableColumn row:row];
    NSTableCellView *cellView = [aTableView makeViewWithIdentifier:identifier owner:self];
    if (cellView == nil)
    {
      // Create cell view
      cellView = [[[NSTableCellView alloc] initWithFrame:[cellView frame]] autorelease];
      cellView.identifier = identifier;
      // Create text field
      NSTextField *textField = [[[NSTextField alloc] initWithFrame:[cellView frame]] autorelease];
      [textField setIdentifier:identifier];
      [textField setBordered:NO];
      [textField setDrawsBackground:NO];
      [textField setStringValue: stringValue];
      cellView.textField = textField;
      [cellView addSubview:textField];
      return cellView:
    }

    [cellView.textField stringValue];
    return cellView;
    }

    The problem here is that I don't have any idea where and how to get and set the frame of the cell. As you can see during the creation of NSTableCellView I'm basically using an NSZeroRect because [cellView frame] is nil. I subclassed NSTableCellView and added a red color for the background in order to see if the NSZeroRect gets automatically updated to the current cell rect - it does work. But it just doesn't make sense to create a subview of NSTableCellView with a zero-frame... is there a method inside NSTableCellView I should subclass and position the NSTextField? Or is it common to get the frame inside -viewForTableColumn and adjusting the text field there? What's the way Apple had in mind concerning programmatically creating a view-based NSTableView? I couldn't find a lot of information on this, the demo video on developer.apple.com directly uses an NSTextField as the return cell-view but my view needs to be more complex than that. I am pretty sure I just missed something very important here. ;-) And my second question is - is it possible to create a cell view which is bigger than one row, thus it's overlaying other rows (I'm not customizing my table view to death, I have a good reason for cell views being positioned over several rows).

    Thank you very much in advance!
  • This isn't an answer but, if you didn't find it, the Table View
    Programming Guide has been quite useful for me:
    https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Tab
    leView/

    You can find it with the following link, then filtering the results by
    unchecking the boxes on the left that don't apply to your situation.
    https://developer.apple.com/search/index.php?q=NSTableView

    Chuck

    On 7/11/12 3:06 PM, "TJ" <tobias...> wrote:

    > Hey guys,
    >
    > I'm trying to replace my old cell-based NSTableView system with the new
    > 10.7+ view-based one without using Xcode's Interface Builder for the
    > table view and column creation.
    > What I am doing now is creating an NSTableCellView inside NSTableView's
    > delegate method [-NSTableView tableView:viewForTableColumn:row:]:
    >
    > - (NSView *)tableView:(NSOutlineView *)aTableView
    > viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
    > {
    > NSString *identifier = [tableColumn identifier];
    > NSString *stringValue = [self tableView:aTableView
    > objectValueForTableColumn:tableColumn row:row];
    > NSTableCellView *cellView = [aTableView
    > makeViewWithIdentifier:identifier owner:self];
    > if (cellView == nil)
    > {
    > // Create cell view
    > cellView = [[[NSTableCellView alloc] initWithFrame:[cellView frame]]
    > autorelease];
    > cellView.identifier = identifier;
    > // Create text field
    > NSTextField *textField = [[[NSTextField alloc] initWithFrame:[cellView
    > frame]] autorelease];
    > [textField setIdentifier:identifier];
    > [textField setBordered:NO];
    > [textField setDrawsBackground:NO];
    > [textField setStringValue: stringValue];
    > cellView.textField = textField;
    > [cellView addSubview:textField];
    > return cellView:
    > }
    >
    > [cellView.textField stringValue];
    > return cellView;
    > }
    >
    > The problem here is that I don't have any idea where and how to get and
    > set the frame of the cell. As you can see during the creation of
    > NSTableCellView I'm basically using an NSZeroRect because [cellView
    > frame] is nil. I subclassed NSTableCellView and added a red color for the
    > background in order to see if the NSZeroRect gets automatically updated
    > to the current cell rect - it does work. But it just doesn't make sense
    > to create a subview of NSTableCellView with a zero-frame... is there a
    > method inside NSTableCellView I should subclass and position the
    > NSTextField? Or is it common to get the frame inside -viewForTableColumn
    > and adjusting the text field there? What's the way Apple had in mind
    > concerning programmatically creating a view-based NSTableView? I couldn't
    > find a lot of information on this, the demo video on developer.apple.com
    > directly uses an NSTextField as the return cell-view but my view needs to
    > be more complex than that. I am pretty sure I just missed something very
    > important here. ;-) And my second question is - is it possible to create
    > a cell view which is bigger than one row, thus it's overlaying other rows
    > (I'm not customizing my table view to death, I have a good reason for
    > cell views being positioned over several rows).
    >
    > Thank you very much in advance!
  • On Mac OS X, look for NSTableViewDelegate tableView:heightOfRow:. The width is set through the NSTableColumn which has an entire set of methods to set the minimum width, the width and the maximum width.

    -Laurent.
    --
    Laurent Daudelin
    AIM/iChat/Skype:LaurentDaudelin                 http://www.nemesys-soft.com/
    Logiciels Nemesys Software                    <laurent...>

    On Jul 11, 2012, at 15:06, TJ <tobias...> wrote:

    > Hey guys,
    >
    > I'm trying to replace my old cell-based NSTableView system with the new 10.7+ view-based one without using Xcode's Interface Builder for the table view and column creation.
    > What I am doing now is creating an NSTableCellView inside NSTableView's delegate method [-NSTableView tableView:viewForTableColumn:row:]:
    >
    > - (NSView *)tableView:(NSOutlineView *)aTableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
    > {
    > NSString *identifier = [tableColumn identifier];
    > NSString *stringValue = [self tableView:aTableView objectValueForTableColumn:tableColumn row:row];
    > NSTableCellView *cellView = [aTableView makeViewWithIdentifier:identifier owner:self];
    > if (cellView == nil)
    > {
    > // Create cell view
    > cellView = [[[NSTableCellView alloc] initWithFrame:[cellView frame]] autorelease];
    > cellView.identifier = identifier;
    > // Create text field
    > NSTextField *textField = [[[NSTextField alloc] initWithFrame:[cellView frame]] autorelease];
    > [textField setIdentifier:identifier];
    > [textField setBordered:NO];
    > [textField setDrawsBackground:NO];
    > [textField setStringValue: stringValue];
    > cellView.textField = textField;
    > [cellView addSubview:textField];
    > return cellView:
    > }
    >
    > [cellView.textField stringValue];
    > return cellView;
    > }
    >
    > The problem here is that I don't have any idea where and how to get and set the frame of the cell. As you can see during the creation of NSTableCellView I'm basically using an NSZeroRect because [cellView frame] is nil. I subclassed NSTableCellView and added a red color for the background in order to see if the NSZeroRect gets automatically updated to the current cell rect - it does work. But it just doesn't make sense to create a subview of NSTableCellView with a zero-frame... is there a method inside NSTableCellView I should subclass and position the NSTextField? Or is it common to get the frame inside -viewForTableColumn and adjusting the text field there? What's the way Apple had in mind concerning programmatically creating a view-based NSTableView? I couldn't find a lot of information on this, the demo video on developer.apple.com directly uses an NSTextField as the return cell-view but my view needs to be more complex than that. I am pretty sure I just missed something very important here. ;-) And my second question is - is it possible to create a cell view which is bigger than one row, thus it's overlaying other rows (I'm not customizing my table view to death, I have a good reason for cell views being positioned over several rows).
  • On Jul 11, 2012, at 15:06 , TJ wrote:

    > The problem here is that I don't have any idea where and how to get and set the frame of the cell. As you can see during the creation of NSTableCellView I'm basically using an NSZeroRect because [cellView frame] is nil. I subclassed NSTableCellView and added a red color for the background in order to see if the NSZeroRect gets automatically updated to the current cell rect - it does work. But it just doesn't make sense to create a subview of NSTableCellView with a zero-frame... is there a method inside NSTableCellView I should subclass and position the NSTextField? Or is it common to get the frame inside -viewForTableColumn and adjusting the text field there? What's the way Apple had in mind concerning programmatically creating a view-based NSTableView? I couldn't find a lot of information on this, the demo video on developer.apple.com directly uses an NSTextField as the return cell-view but my view needs to be more complex than that. I am pretty sure I just missed something very important here. ;-)

    The cell view creation occurs earlier than the point where the cell view's geometry (including its frame) is configured for the row where it's going to be used. (Note that you're only creating the view if there isn't one to reuse, and the re-used one will have the "wrong" frame from wherever it was last used.)

    You never set the frame yourself. The table view does that.

    In a circumstance like this, you can create the view with any frame you want, because it will be re-sized and re-positioned later. The only real consideration is that, depending on the intended subviews, you may choose *not* to make the view very small, because autoresizing of subviews of a view that's too small to contain them may produce undesirable results.

    So, use an empty frame rect, or a 100 x 100 frame rect or a 1000 x 1000 frame rect or whatever is convenient for the purpose of initially creating the view.

    > And my second question is - is it possible to create a cell view which is bigger than one row, thus it's overlaying other rows (I'm not customizing my table view to death, I have a good reason for cell views being positioned over several rows).

    I dunno, but I doubt that it works. The table view re-uses cell views that are scrolled out of the content view, and I suspect it bases this on the row height, not the row's cell view's frame rect. In addition, I'd imagine that overlapping rows might mess up row animations. Lastly, your view is going to be resized by the table view itself, so your attempt to re-size is might be frustrated anyway.

    P.S. Here's a documentation reference:

    https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Tab
    leView/PopulatingView-TablesProgrammatically/PopulatingView-TablesProgramma
    tically.html#//apple_ref/doc/uid/10000026i-CH14-SW5


    which has sample code similar to yours. Note the comment that says, "the height of the frame is not really relevant, the row-height will modify the height".
  • Hey guys,

    Thank you all for your useful answers, Chuck, Laurent and Quincey, you guys rock! Fixed the issue.

    Best
    – Toby

    On Jul 12, 2012, at 2:24 AM, Quincey Morris wrote:

    > On Jul 11, 2012, at 15:06 , TJ wrote:
    >
    >> The problem here is that I don't have any idea where and how to get and set the frame of the cell. As you can see during the creation of NSTableCellView I'm basically using an NSZeroRect because [cellView frame] is nil. I subclassed NSTableCellView and added a red color for the background in order to see if the NSZeroRect gets automatically updated to the current cell rect - it does work. But it just doesn't make sense to create a subview of NSTableCellView with a zero-frame... is there a method inside NSTableCellView I should subclass and position the NSTextField? Or is it common to get the frame inside -viewForTableColumn and adjusting the text field there? What's the way Apple had in mind concerning programmatically creating a view-based NSTableView? I couldn't find a lot of information on this, the demo video on developer.apple.com directly uses an NSTextField as the return cell-view but my view needs to be more complex than that. I am pretty sure I just missed something very important here. ;-)
    >
    > The cell view creation occurs earlier than the point where the cell view's geometry (including its frame) is configured for the row where it's going to be used. (Note that you're only creating the view if there isn't one to reuse, and the re-used one will have the "wrong" frame from wherever it was last used.)
    >
    > You never set the frame yourself. The table view does that.
    >
    > In a circumstance like this, you can create the view with any frame you want, because it will be re-sized and re-positioned later. The only real consideration is that, depending on the intended subviews, you may choose *not* to make the view very small, because autoresizing of subviews of a view that's too small to contain them may produce undesirable results.
    >
    > So, use an empty frame rect, or a 100 x 100 frame rect or a 1000 x 1000 frame rect or whatever is convenient for the purpose of initially creating the view.
    >
    >> And my second question is - is it possible to create a cell view which is bigger than one row, thus it's overlaying other rows (I'm not customizing my table view to death, I have a good reason for cell views being positioned over several rows).
    >
    > I dunno, but I doubt that it works. The table view re-uses cell views that are scrolled out of the content view, and I suspect it bases this on the row height, not the row's cell view's frame rect. In addition, I'd imagine that overlapping rows might mess up row animations. Lastly, your view is going to be resized by the table view itself, so your attempt to re-size is might be frustrated anyway.
    >
    >
    > P.S. Here's a documentation reference:
    >
    > https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Tab
    leView/PopulatingView-TablesProgrammatically/PopulatingView-TablesProgramma
    tically.html#//apple_ref/doc/uid/10000026i-CH14-SW5

    >
    > which has sample code similar to yours. Note the comment that says, "the height of the frame is not really relevant, the row-height will modify the height".
    >
  • On Jul 12, 2012, at 2:24 AM, Quincey Morris <quinceymorris...> wrote:

    > On Jul 11, 2012, at 15:06 , TJ wrote:
    >
    >> The problem here is that I don't have any idea where and how to get and set the frame of the cell. As you can see during the creation of NSTableCellView I'm basically using an NSZeroRect because [cellView frame] is nil. I subclassed NSTableCellView and added a red color for the background in order to see if the NSZeroRect gets automatically updated to the current cell rect - it does work. But it just doesn't make sense to create a subview of NSTableCellView with a zero-frame... is there a method inside NSTableCellView I should subclass and position the NSTextField? Or is it common to get the frame inside -viewForTableColumn and adjusting the text field there? What's the way Apple had in mind concerning programmatically creating a view-based NSTableView? I couldn't find a lot of information on this, the demo video on developer.apple.com directly uses an NSTextField as the return cell-view but my view needs to be more complex than that. I am pretty sure I just missed something very important here. ;-)
    >
    > The cell view creation occurs earlier than the point where the cell view's geometry (including its frame) is configured for the row where it's going to be used. (Note that you're only creating the view if there isn't one to reuse, and the re-used one will have the "wrong" frame from wherever it was last used.)
    >
    > You never set the frame yourself. The table view does that.
    >
    > In a circumstance like this, you can create the view with any frame you want, because it will be re-sized and re-positioned later. The only real consideration is that, depending on the intended subviews, you may choose *not* to make the view very small, because autoresizing of subviews of a view that's too small to contain them may produce undesirable results.
    >
    > So, use an empty frame rect, or a 100 x 100 frame rect or a 1000 x 1000 frame rect or whatever is convenient for the purpose of initially creating the view.
    >

    Or, if you really need it, you can use the value from frameOfCellAtColumn:row:  -- that is the value that the table is going to set on the returned "cell view". The method is pretty fast, so it should be okay to call. However, it will be faster to just use a hardcoded value for initial layout (like 100x100, or column.width x rowHeight -- and if you want to get even more fancy, subtract half the intercellSpacing from each.)

    corbin

    >> And my second question is - is it possible to create a cell view which is bigger than one row, thus it's overlaying other rows (I'm not customizing my table view to death, I have a good reason for cell views being positioned over several rows).
    >
    > I dunno, but I doubt that it works. The table view re-uses cell views that are scrolled out of the content view, and I suspect it bases this on the row height, not the row's cell view's frame rect. In addition, I'd imagine that overlapping rows might mess up row animations. Lastly, your view is going to be resized by the table view itself, so your attempt to re-size is might be frustrated anyway.
    >
    >
    > P.S. Here's a documentation reference:
    >
    > https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Tab
    leView/PopulatingView-TablesProgrammatically/PopulatingView-TablesProgramma
    tically.html#//apple_ref/doc/uid/10000026i-CH14-SW5

    >
    > which has sample code similar to yours. Note the comment that says, "the height of the frame is not really relevant, the row-height will modify the height".
previous month july 2012 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today