Issue when hiding NSTableColumn while resizing

  • Hello all,

    I am working on implementing a manual behavior on NSTableView's column
    resizing. Because it also needs to be live resizing (whenever the window or
    another column is resized), I have subclassed NSTableColumn and overriden
    `-setWidth:', which will call a delegate, which in turn will call a method
    that adjusts the size of each column so that they resize the way we want.
    The same method is called whenever the application window is resized.

    The idea, basically, is that the first column is the most important one, and
    should not be resized until all others are at their minimum size, or, and this
    is the crucial part, have been hidden.
    Whenever the window or a column is resized, here is the desired scenario:
    (Note that column 2 has a fixed size and is thus never mentioned)
    - Column 5 is resized until it reaches its min width
    - Column 4 is resized until it reaches its min width
    - Column 3 is resized until it reaches its min width
    - Column 5 is hidden
    - Column 4 is hidden
    - Column 1 is finally resized until it reaches its minimum width

    My implementation with `-setWidth:' and its delegate works pretty well, except
    I have been experiencing a crash.
    When resizing the window, it works okay. The only thing is that it may
    crash when resizing another column after that. Here is how I reproduce it:
    - Resize the window so that at least column 5 is hidden
    - Resize column 1 again so that column 5 is visible

    Then, the following crash happens as soon as I release the mouse:
    *** Assertion failure in -[MyTableColumn _enableResizedPosting]
    EXC_0001_NAME:NSInternalInconsistencyException
    EXC_0001_REASON:Invalid parameter not satisfying:
                                            _cFlags.resizedPostingDisableCount > 0

    Funny thing is that it does not happen if I resize any column to get to the
    situation where column 5 is hidden. It only works when I resize the window to
    do so.

    After different tests, it looks like NSTableColumn is not happy whenever a
    column is hidden *before* the column resizing happens, but is visible after,
    when trying to post the "column did resize" notification.
    It seemed as if when handling the "mouse down" event, the visible columns are
    initialized/prepared to be resized.

    This is why, in my NSTableColumn subclass, I tried to override the -mouseDown:
    method, and there, I would simply iterate over all the columns and unhide
    them. And guess what? It works! My "resize delegate" will hide the needed
    columns after that anyway.
    Obvisouly though, I have a visual glitch where you can see all the columns for
    a split second (even if they are supposed to be hidden).

    The problem in the end is that not only do I have a visual glitch, but this
    also feels like a very hacky/dirty solution, and hence, not the way to go.
    I feel like I probably should not be trying to hide columns while some others
    are resized. It works most of the time though, so this is very confusing.

    Does anyone have any better ideas?

    Sincerely,--
    Thibault Martin-Lagardette
  • On May 1, 2012, at 06:40 , Thibault Martin-Lagardette wrote:

    > The problem in the end is that not only do I have a visual glitch, but this
    > also feels like a very hacky/dirty solution, and hence, not the way to go.
    > I feel like I probably should not be trying to hide columns while some others
    > are resized. It works most of the time though, so this is very confusing.

    What happens if you *don't* hide columns at all, but change your resizing code to set the width to 0 when a "hideable" column reaches its nominal min width? (Of course, you'd have to set the actual minWidth to 0 first.)

    If it turns out you must hide columns for other reasons (for example, the "hideable" columns are editable), then you could arrange to actually hide them at the end of the resizing process -- and you'd have to show them at the start, I suppose.

    Alternatively, assuming the table doesn't use a horizontal scroller, how about pushing "collapsed" columns (columns that have gone below their min width) out of the table view's bounds by resizing the non-collapsed columns? I'm not sure, but I think this might work given the position and order in which your columns should disappear.
  • On May 1, 2012, at 06:40 , Thibault Martin-Lagardette wrote:

    > The problem in the end is that not only do I have a visual glitch, but this
    > also feels like a very hacky/dirty solution, and hence, not the way to go.
    > I feel like I probably should not be trying to hide columns while some others
    > are resized. It works most of the time though, so this is very confusing.

    If you can't find any alternate solution, [NSWindow disableFlushWindow] is useful for hiding those visual glitches.
  • On 6 May 2012, at 08:22, Quincey Morris wrote:

    On May 1, 2012, at 06:40 , Thibault Martin-Lagardette wrote:

    The problem in the end is that not only do I have a visual glitch, but this
    also feels like a very hacky/dirty solution, and hence, not the way to go.
    I feel like I probably should not be trying to hide columns while some others
    are resized. It works most of the time though, so this is very confusing.

    What happens if you *don't* hide columns at all, but change your resizing code to set the width to 0 when a "hideable" column reaches its nominal min width? (Of course, you'd have to set the actual minWidth to 0 first.)

    If it turns out you must hide columns for other reasons (for example, the "hideable" columns are editable), then you could arrange to actually hide them at the end of the resizing process -- and you'd have to show them at the start, I suppose.

    Alternatively, assuming the table doesn't use a horizontal scroller, how about pushing "collapsed" columns (columns that have gone below their min width) out of the table view's bounds by resizing the non-collapsed columns? I'm not sure, but I think this might work given the position and order in which your columns should disappear.

    I haven't tried the `width = 0' instead of hidden, but I'm a little afraid of
    how hacky this sounds, haha. And also afraid we might still see the columns
    separators stacked onto each other.

    Also, we do need to have the resize being live, and it is actually the root
    problem of all this, otherwise resizing at the end of the resize process works
    perfectly well. But this is not the expected behavior, haha.

    But yes, there is, in fact, no horizontal scroller, so this is definitely a
    possible alternative, though maybe a little more complex because of other
    implications, but still feasible.

    Thanks for the input!

    Sincerely,
    --
    Thibault Martin-Lagardette
previous month may 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