5 Replies Latest reply: Aug 18, 2012 11:08 AM by etresoft
tereno10 Level 1 Level 1 (0 points)

Hi everyone,

 

I just began writing OSX apps not too long ago. I'm having trouble with dynamically setting my row heights for an NSTableView. I've seen a really old solution where the subclass the view but I also found a solution posted by Corbin on Stack Overflow. However, I don't quite understand and am hoping someone has sample code?

 

For my usecase, I have a list of text of varying lengths and are displayed in a multi-line text field. The rows for the table cut off the text and so I'm trying to resize them to fit the text. When I check on the setRowSizeStyle to custom - it defaults to 71 and is fixed at 71. I hope someone can help me out. I think the solution posted by Corbin should solve my problem but I have no idea how to implement it.

 

Thanks

  • 1. Re: Dynamic row heights for NSTableView
    etresoft Level 7 Level 7 (24,270 points)

    First of all, I suggest using the new view-based tables. That makes things much easier.

     

    Just define:

     

    - (CGFloat) tableView: (NSTableView *) tableView

      heightOfRow: (NSInteger) row;

     

    in your table view delegate.

     

    it is a little tricky to actually calculate the height you need. You can start with something like the following. Pass in the maximum size of a cell in your table.

     

    // Determine the ideal height for the content width.

    - (CGFloat) calculateIdealHeightForSize: (NSSize) size

      {

      NSTextStorage * storage =

        [[NSTextStorage alloc] initWithAttributedString: self.content];

         

      NSTextContainer * container =

        [[NSTextContainer alloc] initWithContainerSize: size];

      NSLayoutManager * manager = [[NSLayoutManager alloc] init];

         

      [manager addTextContainer: container];

      [storage addLayoutManager: manager];

        

      [manager glyphRangeForTextContainer: container];

       

      NSRect idealRect = [manager usedRectForTextContainer: container];

         

      [manager release];

      [container release];

      [storage release];

       

      // Include a fudge factor.

      return idealRect.size.height + 25;

      }

  • 2. Re: Dynamic row heights for NSTableView
    tereno10 Level 1 Level 1 (0 points)

    Thanks. I am using the view-based tables but I guess I am confused. I have implemented heightOfRow but it is repeatedly calculating 71. Perhaps my calculation is wrong but I'm glad I'm on the right track.

     

    When I get home later tonight, I'll post some code. I've also read about having to call -noteHeightOfRowsWithIndexesChanged: but I'm trying to figure out a suitable place for calling this.

  • 3. Re: Dynamic row heights for NSTableView
    etresoft Level 7 Level 7 (24,270 points)

    You only need to call that if your row size is actively changing. If you know what it should be right away, it shouldn't be necessary.

  • 4. Re: Dynamic row heights for NSTableView
    tereno10 Level 1 Level 1 (0 points)

    Etresoft, the function that you gave me for some reason constantly calculates the height as 39. Minus the fudge factor of 25 means I'm constantly getting 14 for my height for all rows and some of the text is cut off. I think it might be because I'm passing in the wrong size into my NSTextContainer.

     

    Here's my code right now:

     

    - (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row

    {

        Message *message = [thread objectAtIndex:row];

        NSTableColumn *tableColoumn = [conversationView

                                       tableColumnWithIdentifier:@"tableColumn"];

        if (tableColoumn)

        {

            NSCell *dataCell = [tableColoumn dataCell];

     

            [dataCell setWraps:YES];

            [dataCell setStringValue:message.message];

            CGFloat height = [self calculateIdealHeightForSize:[dataCell cellSize] content:message.message];

            NSLog(@"Message: %@ Height: %f", message.message, height);

            return height;

        }

        NSLog(@"No size found. Returning default size for 100.");

        return 100;

    }

     

    - (CGFloat) calculateIdealHeightForSize: (NSSize) size content: (NSString *) content

    {

        NSTextStorage * storage =

        [[NSTextStorage alloc] initWithAttributedString:[[NSAttributedString alloc] initWithString: content ]];

     

        NSTextContainer * container =

        [[NSTextContainer alloc] initWithContainerSize: size];

        NSLayoutManager * manager = [[NSLayoutManager alloc] init];

     

        [manager addTextContainer: container];

        [storage addLayoutManager: manager];

     

        [manager glyphRangeForTextContainer: container];

     

        NSRect idealRect = [manager usedRectForTextContainer: container];

     

        // Include a fudge factor.

        return idealRect.size.height + 25;

    }

  • 5. Re: Dynamic row heights for NSTableView
    etresoft Level 7 Level 7 (24,270 points)

    That looks like a cell-based table to me. There is nothing wrong with that, but I haven't used one of those recently.

     

    The problem is that you are passing the current, small size of the cell into "calculateIdealHeightForSize". It isn't going to do much with that. You have to pass the maximum size of the cell. It will attempt to layout the text in that area and return the height required. You may have to worry about borders in the cell and the layout method. I have seen suggestions that you should use the only 10.2 layout method, but I'm not sure that is true anymore.