Outline view and horizontal scrolling

  • I have an outline view which can grow and shrink when the window
    resizes. It has one table column; I'm hiding the header since there's
    only one column and it doesn't really make sense to show it.

    By default I've found that this single column will grow and shrink
    itself dynamically as the window resizes to match the outline view's
    size. This means that I never get a horizontal scroll bar unless the
    outline view gets smaller than the column's minimum width, even when
    items in the outline view are actually truncated. The behavior I'd like
    to see is a horizontal scroll bar appearing whenever any of the outline
    view's items get clipped, but I can't figure out an easy way to do this.

    If I could make the column's minimum width automatically track the
    longest /visible/ item inside the outline view, I think it would work
    the way I want it to, but that doesn't appear to be an option (short of
    recalculating the min-width every time the user opens or closes a
    triangle). The best option I've thought of so far would be to find the
    widest item in the outline view and set the column minimum width to that
    value, but that isn't perfect either—when the widest item is hidden
    behind a closed triangle, we'd see a scroll bar for no reason.

    Is this solvable or should I just accept defeat and set the column's
    minimum width to the width of the widest item in the whole tree? (Or
    will Cocoa do some magic behind the scenes so that this will all "just
    work?")
  • OK, so I've been trying to implement the "accepting defeat" solution and
    even that is proving to be a challenge.
    I can't seem to find a way to properly determine the width of the
    "indentation marker" (the disclosure triangle) and there doesn't appear
    to be one. The icon itself is 16 pixels across, but there's padding as
    well and I don't want to just hard-code a value unless I have to.
    Because of this, I come up short by 25 pixels or so when I do this:

        NSAttributedString* str = ... my item's title ...;
        int level = ... the depth of my item in the tree ...;
        float indent = [outlineView indentationPerLevel];
        float width = [str size].width + (indent * level);

    Is there a better way that I'm missing? I never would have guessed that
    this would be difficult.
    Leopard added a method "frameOfOutlineCellAtRow:" which would probably
    do the right thing, but I'm not ready to require Leopard just for this
    (I am using the 10.4 SDK so it was inconvenient to even see if this
    generated good results or not).

    John Stiles wrote:
    > I have an outline view which can grow and shrink when the window
    > resizes. It has one table column; I'm hiding the header since there's
    > only one column and it doesn't really make sense to show it.
    >
    > By default I've found that this single column will grow and shrink
    > itself dynamically as the window resizes to match the outline view's
    > size. This means that I never get a horizontal scroll bar unless the
    > outline view gets smaller than the column's minimum width, even when
    > items in the outline view are actually truncated. The behavior I'd
    > like to see is a horizontal scroll bar appearing whenever any of the
    > outline view's items get clipped, but I can't figure out an easy way
    > to do this.
    >
    > If I could make the column's minimum width automatically track the
    > longest /visible/ item inside the outline view, I think it would work
    > the way I want it to, but that doesn't appear to be an option (short
    > of recalculating the min-width every time the user opens or closes a
    > triangle). The best option I've thought of so far would be to find the
    > widest item in the outline view and set the column minimum width to
    > that value, but that isn't perfect either—when the widest item is
    > hidden behind a closed triangle, we'd see a scroll bar for no reason.
    >
    > Is this solvable or should I just accept defeat and set the column's
    > minimum width to the width of the widest item in the whole tree? (Or
    > will Cocoa do some magic behind the scenes so that this will all "just
    > work?")
  • On Dec 4, 2007, at 4:41 PM, John Stiles wrote:

    > OK, so I've been trying to implement the "accepting defeat"
    > solution and even that is proving to be a challenge.
    > I can't seem to find a way to properly determine the width of the
    > "indentation marker" (the disclosure triangle) and there doesn't
    > appear to be one. The icon itself is 16 pixels across, but there's
    > padding as well and I don't want to just hard-code a value unless I
    > have to. Because of this, I come up short by 25 pixels or so when I
    > do this:
    >
    > NSAttributedString* str = ... my item's title ...;
    > int level = ... the depth of my item in the tree ...;
    > float indent = [outlineView indentationPerLevel];
    > float width = [str size].width + (indent * level);
    >
    > Is there a better way that I'm missing? I never would have guessed
    > that this would be difficult.
    > Leopard added a method "frameOfOutlineCellAtRow:" which would
    > probably do the right thing, but I'm not ready to require Leopard
    > just for this (I am using the 10.4 SDK so it was inconvenient to
    > even see if this generated good results or not).

    Try -frameOfCellAtColumn:row: (a method from NSTableView). I believe
    that should already have the indentation applied to it (so the
    origin.x will be where your string starts), so you ought to be able
    to just add on the string width to the rect's origin.x.

    Hope this helps,
    - Greg
  • I tried

        NSRect r = [outlineView frameOfCellAtColumn:0 row:[outlineView
    rowForItem:item]];

    but this seems to consistently give me a rectangle at origin (16, 0)
    with size (-16, 0), regardless of the item's actual depth within the tree.
    Weird.

    Greg Titus wrote:
    >
    > On Dec 4, 2007, at 4:41 PM, John Stiles wrote:
    >
    >> OK, so I've been trying to implement the "accepting defeat" solution
    >> and even that is proving to be a challenge.
    >> I can't seem to find a way to properly determine the width of the
    >> "indentation marker" (the disclosure triangle) and there doesn't
    >> appear to be one. The icon itself is 16 pixels across, but there's
    >> padding as well and I don't want to just hard-code a value unless I
    >> have to. Because of this, I come up short by 25 pixels or so when I
    >> do this:
    >>
    >> NSAttributedString* str = ... my item's title ...;
    >> int level = ... the depth of my item in the tree ...;
    >> float indent = [outlineView indentationPerLevel];
    >> float width = [str size].width + (indent * level);
    >>
    >> Is there a better way that I'm missing? I never would have guessed
    >> that this would be difficult.
    >> Leopard added a method "frameOfOutlineCellAtRow:" which would
    >> probably do the right thing, but I'm not ready to require Leopard
    >> just for this (I am using the 10.4 SDK so it was inconvenient to even
    >> see if this generated good results or not).
    >
    > Try -frameOfCellAtColumn:row: (a method from NSTableView). I believe
    > that should already have the indentation applied to it (so the
    > origin.x will be where your string starts), so you ought to be able to
    > just add on the string width to the rect's origin.x.
    >
    > Hope this helps,
    > - Greg
previous month december 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