NSBrowser drawInteriorWithFrame called before willDisplayCell, causing display problems

  • Hello,

    I am experiencing some strange drawing issues with an NSBrowser that
    uses a subclass of NSBrowserCells with the NSBrowserCell also having
    a representedObject set. I'm not sure exactly what is causing the
    problem, but the issue seems to stem from the fact that
    [NSBrowserCell drawInteriorWithFrame:inView:] ends up causing
    [CKDirectoryTreeController browser:willDisplayCell:atRow:column:]
    (the NSBrowser delegate method) to get called after. Since this
    delegate method is where the representedObject is set, when the
    drawInteriorWithFrame:inView method gets called first it does not yet
    have the correct data to draw correctly. I have compared the order of
    the method calls to the SimpleBrowser example and the
    browser:willDisplayCell:atRow:column is always called before the
    drawInteriorWithFrame:inView method, so the problem is not evident.
    Also, any drawing that occurs after these two methods are called in
    the "wrong" order is drawn correctly as the node is set going forward.

    I'd love to find out if I can do anything to prevent the
    drawInteriorWithFrame:inView from being called early. A stack trace
    is below showing the order of the method calls. I've also noticed
    that this occurs in Tiger, but not in Leopard, so something must have
    been updated. However, I need this to work in both OS versions.

    Thanks in advance!
    Bryan

    #0    0x22145f73 in -[CKDirectoryTreeController
    browser:willDisplayCell:atRow:column:] at CKDirectoryTreeController.m:
    1345
    #1    0x93494f21 in -[NSBrowser _sendDelegateWillDisplayCell:atRow:column:]
    #2    0x93495dd4 in -[NSBrowserCell _checkLoaded:rect:highlight:]
    #3    0x934942b4 in -[NSBrowserCell drawInteriorWithFrame:inView:]
    #4    0x22147297 in -[CKDirectoryBrowserCell
    drawInteriorWithFrame:inView:] at CKDirectoryTreeController.m:1683
    #5    0x9332e609 in -[NSMatrix drawRect:]
    #6    0x9331a3d1 in -[NSView _drawRect:clip:]
    #7    0x9331942b in -[NSView
    _recursiveDisplayAllDirtyWithLockFocus:visRect:]
    #8    0x9332b38f in _recursiveDisplayInRect2
    #9    0x9083ead0 in CFArrayApplyFunction
    #10    0x93319633 in -[NSView
    _recursiveDisplayAllDirtyWithLockFocus:visRect:]
    #11    0x9332b38f in _recursiveDisplayInRect2
    #12    0x9083ead0 in CFArrayApplyFunction
    #13    0x93319633 in -[NSView
    _recursiveDisplayAllDirtyWithLockFocus:visRect:]
    #14    0x93318493 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #15    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #16    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #17    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #18    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #19    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #20    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #21    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #22    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #23    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #24    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #25    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #26    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #27    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #28    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #29    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #30    0x93319061 in -[NSView
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #31    0x93317b98 in -[NSThemeFrame
    _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisible
    RectForView:topView:]
    #32    0x93317382 in -[NSView
    _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
    #33    0x93316cae in -[NSView displayIfNeeded]
    #34    0x93316a52 in -[NSWindow displayIfNeeded]
    #35    0x93366d8c in _handleWindowNeedsDisplay
    #36    0x9082dd0e in __CFRunLoopDoObservers
    #37    0x9082cdb0 in CFRunLoopRunSpecific
    #38    0x9082ca6e in CFRunLoopRunInMode
    #39    0x92df4878 in RunCurrentEventLoopInMode
    #40    0x92df3f82 in ReceiveNextEventCommon
    #41    0x92df3dd9 in BlockUntilNextEventMatchingListInMode
    #42    0x9329b485 in _DPSNextEvent
    #43    0x9329b076 in -[NSApplication
    nextEventMatchingMask:untilDate:inMode:dequeue:]
    #44    0x933661f4 in -[NSApplication _realDoModalLoop:peek:]
    #45    0x93364fcb in -[NSApplication runModalForWindow:]
  • > I am experiencing some strange drawing issues with an NSBrowser that
    > uses a subclass of NSBrowserCells with the NSBrowserCell also having
    > a representedObject set. I'm not sure exactly what is causing the
    > problem, but the issue seems to stem from the fact that
    > [NSBrowserCell drawInteriorWithFrame:inView:] ends up causing
    > [CKDirectoryTreeController browser:willDisplayCell:atRow:column:]
    > (the NSBrowser delegate method) to get called after. Since this
    > delegate method is where the representedObject is set, when the
    > drawInteriorWithFrame:inView method gets called first it does not
    > yet have the correct data to draw correctly. I have compared the
    > order of the method calls to the SimpleBrowser example and the
    > browser:willDisplayCell:atRow:column is always called before the
    > drawInteriorWithFrame:inView method, so the problem is not evident.
    > Also, any drawing that occurs after these two methods are called in
    > the "wrong" order is drawn correctly as the node is set going forward.

    Bryan, what appearance are you trying to achieve? Getting this
    subclassing right on Tiger involves overriding some private methods,
    so it’d be best to make sure that it’s really necessary before you
    take that route.

    -Ben
  • On Nov 27, 2007, at 2:26 PM, Benjamin Stiglitz wrote:

    >> I am experiencing some strange drawing issues with an NSBrowser
    >> that uses a subclass of NSBrowserCells with the NSBrowserCell also
    >> having a representedObject set. I'm not sure exactly what is
    >> causing the problem, but the issue seems to stem from the fact that
    >> [NSBrowserCell drawInteriorWithFrame:inView:] ends up causing
    >> [CKDirectoryTreeController browser:willDisplayCell:atRow:column:]
    >> (the NSBrowser delegate method) to get called after. Since this
    >> delegate method is where the representedObject is set, when the
    >> drawInteriorWithFrame:inView method gets called first it does not
    >> yet have the correct data to draw correctly. I have compared the
    >> order of the method calls to the SimpleBrowser example and the
    >> browser:willDisplayCell:atRow:column is always called before the
    >> drawInteriorWithFrame:inView method, so the problem is not evident.
    >> Also, any drawing that occurs after these two methods are called in
    >> the "wrong" order is drawn correctly as the node is set going
    >> forward.
    >
    > Bryan, what appearance are you trying to achieve? Getting this
    > subclassing right on Tiger involves overriding some private methods,
    > so it’d be best to make sure that it’s really necessary before you
    > take that route.

    Ben and I talked about this; unfortunately, you are running into a bug
    in NSBrowser which has been fixed on Leopard. To work around it, do
    something like this:

    if (![self isLoaded]) {
        [[browser delegate] browser:browser willDisplayCell:cell
    atRow:column:]; // row/col can be acquired through the public browser
    API.
        [self setLoaded:YES];
    ... do your drawing.

    corbin
  • Corbin and Ben,

    Thanks for the support here. The code Corbin provided has fixed our
    problem! Thanks so much for the help.

    Bryan

    On Nov 27, 2007, at 4:40 PM, Corbin Dunn wrote:

    >
    > On Nov 27, 2007, at 2:26 PM, Benjamin Stiglitz wrote:
    >
    >>> I am experiencing some strange drawing issues with an NSBrowser
    >>> that uses a subclass of NSBrowserCells with the NSBrowserCell
    >>> also having a representedObject set. I'm not sure exactly what is
    >>> causing the problem, but the issue seems to stem from the fact
    >>> that [NSBrowserCell drawInteriorWithFrame:inView:] ends up
    >>> causing [CKDirectoryTreeController
    >>> browser:willDisplayCell:atRow:column:]  (the NSBrowser delegate
    >>> method) to get called after. Since this delegate method is where
    >>> the representedObject is set, when the
    >>> drawInteriorWithFrame:inView method gets called first it does not
    >>> yet have the correct data to draw correctly. I have compared the
    >>> order of the method calls to the SimpleBrowser example and the
    >>> browser:willDisplayCell:atRow:column is always called before the
    >>> drawInteriorWithFrame:inView method, so the problem is not
    >>> evident. Also, any drawing that occurs after these two methods
    >>> are called in the "wrong" order is drawn correctly as the node is
    >>> set going forward.
    >>
    >> Bryan, what appearance are you trying to achieve? Getting this
    >> subclassing right on Tiger involves overriding some private
    >> methods, so it’d be best to make sure that it’s really necessary
    >> before you take that route.
    >
    > Ben and I talked about this; unfortunately, you are running into a
    > bug in NSBrowser which has been fixed on Leopard. To work around
    > it, do something like this:
    >
    > if (![self isLoaded]) {
    > [[browser delegate] browser:browser willDisplayCell:cell
    > atRow:column:]; // row/col can be acquired through the public
    > browser API.
    > [self setLoaded:YES];
    > ... do your drawing.
    >
    > corbin
previous month november 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    
Go to today