4

I have an NSTableView, which should resize it's frame when a row is added. I would make 2 properties, maxHeight and minHeight, and if any rows are being added or removed, I would resize the table view to fit it's content, if it doesn't cross the limit.

Like the Safari Download Panel (10.7 or later). Has anyone an idea how to do this? I would want to handle this in a subclass. So no messing with the resizing in the delegate class.

I would at least need to know which method is being called when the table view is being reloaded. reloadTable only invokes the real reloading method, so no success there.

IluTov
  • 6,807
  • 6
  • 41
  • 103
  • I've posted an answer to a similar problem recently. You can find it here: http://stackoverflow.com/a/44093345/3184888 – JanApotheker May 21 '17 at 05:42

1 Answers1

4

I did something similar a while back and I did it on the controller, not on a subclass (sorry if it's not what you're looking for). Basically I wrote a method that computed the height of the tableview by adding the height of all the rows. And every time I added or removed a row from the table I'd call that method. Here is something to get you started:

- (void)adjustTableSize
{
    NSInteger minHeight = ...
    NSInteger maxHeight = ...

    NSInteger tViewHeight = 0;
    for (int i = 0; i < [tableView numberOfRows]; i++) {
        NSView* v = [tableView viewAtColumn: 0 row: i makeIfNecessary: YES]; // Note that this is for view-based tableviews
        tViewHeight += v.frame.size.height;
    }

    NSInteger result = MIN(MAX(tViewHeight, minHeight), maxHeight);

    // Do something with result here
}

If you really want it on a subclass it should possible, but it might be a pain to work out how...

EDIT:

If you don't mind working with undocummented APIs, here's a simpler version:

- (void)adjustTableSize
{
    NSInteger minHeight = ...
    NSInteger maxHeight = ...
    NSInteger result = MIN(MAX([tableView _minimumFrameSize].height, minHeight), maxHeight);

    // Do something with result here
}

Since this is undocummented I can't promise it'll work, but from my testing so far it does. And it might be faster than creating views just to get their height, specially if you have lots of rows.

Alex
  • 5,009
  • 3
  • 39
  • 73
  • This is cool, the only thing to adjust would be to find the right method in the NSTableView subclass. There are tons, as you can see in the class dump above. Have you an idea which one to use? – IluTov Nov 18 '12 at 22:14
  • Oh and btw. you can just use enumerateAvailableRowViewsUsingBlock: – IluTov Nov 18 '12 at 22:15
  • Ok, I have played with it a little bit, and it bugs, a lot. Did you set the frame of the NSScrollView? – IluTov Nov 18 '12 at 23:28
  • Yes, you're right about `enumerateAvailableRowViewsUsingBlock`. No, I really don't know. But... maybe you could subclass `realoadData`, first calling super then doing this (?) And no, I added some padding and set the frame directly to the window that contains the tableview, which means that the table view resizes indirectly. Don't forget that if you're changing the frame of the tableview directly you might be messing with the scrollview that contains it (that's why I think doing it on the controller might be better...). But I didn't do anything to the scrollview either. – Alex Nov 19 '12 at 07:11
  • On second thought, I think enumerateAvailableRowVjewUsingBlock: might not be what we want here. That method includes all the views currently visible, being animated or stored by the tableview. There's no guarantee that the number of views you'll get is the same as the number of rows. If you are using this method and you're having problems, try a for loop. – Alex Nov 19 '12 at 07:45
  • Ok, you're right. But it still bugs, I'll try to resize the window. Thanks – IluTov Nov 19 '12 at 08:05
  • I didn't find a better answer, if I do, I'll let you know :) – IluTov Jan 02 '13 at 19:06