Adaptable NSTableViewHeader

  • Hi everyone,

    My problem is quite hard to explain in just a few words, but I'll give
    it a try. Additionally, I'm attaching an URL to a video shot of the
    running application along with the application project (only one
    custom class, very few lines of code) below so you can test it
    yourself too:

    I have subclassed the NSTableHeaderView class so that when it is
    displayed (e.g. its drawRect is called) it renders additional
    information about the table view above the ordinary table column
    headers. Think of it as two vertical divisions:
    Upper part - Shows some statistics about the table view
    Lower part - Displays the table column headers

    Now, if I set my tableview's headerview to my custom subclass, and
    place the tableview inside a NSScrollView, my custom tableview header
    is displayed just fine. So far, so nice. Now let us assume that the
    statistics are not that important for the user, so as she begins to
    scroll everything that is visible in the clip view (table header view
    + table view) is scrolled - until the only part that's visible in the
    custom NSTableHeaderView class are the table column headers. At this
    stage, the clip view should start to scroll the rows for the table
    view instead, keeping the header locked in the upper part of the clip
    view (just as a tableview with a normal header works when one scrolls).

    I havn't been able to accomplish this in an efficient manner. In the
    attached example (which doesn't perform too much unnecessary rendering
    according to Quartz Debug), it almost works - there are only two
    things that goes wrong; (1) the table rows begins to scroll up "under"
    the header view instantly - I want them to do that first when the
    table header view has "snapped" - and (2) the table view rows don't
    render correctly sometimes (see movie - a part of row 11 gets stuck at
    the bottom of the view in the beginning).

    Any suggestion on how to accomplish this would be more than welcome.

    URL to project: http://arrelid.com/dump/tableTest-project.zip
    URL to video: http://arrelid.com/dump/tableTest.mov

    Thanks in advance
    Mattias
  • On Oct 30, 2007, at 10:24 AM, Mattias Arrelid wrote:

    > [...]
    > Now, if I set my tableview's headerview to my custom subclass, and
    > place the tableview inside a NSScrollView, my custom tableview
    > header is displayed just fine. So far, so nice. Now let us assume
    > that the statistics are not that important for the user, so as she
    > begins to scroll everything that is visible in the clip view (table
    > header view + table view) is scrolled

    The table view and the header view are each in different clip views.
    You scroll through the height of the NSScrollView's documentView.
    That's why the rows in your table view start scrolling before you
    want them to.

    I'd subclass NSScrollView to handle an additional view, for you're
    statistics, which you want to appear above the header.  Implement -
    tile to put it in the right place.  You may need to override -
    reflectScrolledClipView:.  You need to get the scroll view to use the
    combined height of the document view and statistics view as the
    height it scrolls through.  When you scroll down, you need to first
    shrink the visible height of the stats view, and use any left-over
    for normal scrolling of the document view.  Scrolling up is just the
    opposite.

    Clearly it would be a lot easier if you could put the stats under the
    header view, either at the top or bottom of the actual table view,
    but I think you can get it to work the way you want.

    > [...]
    > (2) the table view rows don't render correctly sometimes (see movie
    > - a part of row 11 gets stuck at the bottom of the view in the
    > beginning).

    You need to call -setNeedsDisplay: when after calling setFrame:.  I'm
    guessing you need to do the same after calling -tile.

    By the way, after looking at your code, NSDivideRect() is a handy
    function:

    NSDivideRect([self bounds], &lowerRect, &upperRect, [self
    minimumHeight], NSMaxYEdge);

    --
    Steve
previous month october 2007 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