Preventing default drawing of slider bar in custom NSSlider class

  • Hi

    I wrote a custom NSSlider and NSSliderCell, overrode the "drawKnob:"
    and "drawBarInside:flipped:" of the NSSliderCell and got the stuff I
    want to draw working correctly, but I'm still getting the default
    slider bar behind my slider bar. I intentionally don't call the
    NSSliderCell's superclass which I thought would do the trick,  but no
    luck. How can I get rid of the default?

    Thanks for any help

    Ken

    Here's the slider bar draw method

    - (void) drawBarInside:(NSRect) inRect
        flipped:(BOOL) inFlipped
    {
    NSRect  adjustedRect  = NSMakeRect(inRect.origin.x + 10, 0,
    inRect.size.width - 20, inRect.size.height);

    float  rectHeight  = inRect.size.height,
        leftWidth  = [gSliderTrackLeft size].width,
        rightWidth  = [gSliderTrackRight size].width,
        centerWidth  = adjustedRect.size.width - leftWidth - rightWidth,
        adjustedRight  = adjustedRect.origin.x + adjustedRect.size.width,
        yOffset    = (rectHeight - DefaultSliderBarHeight) / 2;

    NSRect  leftRect  = NSMakeRect(adjustedRect.origin.x,
    adjustedRect.origin.y + yOffset, leftWidth, DefaultSliderBarHeight),
        rightRect  = NSMakeRect(adjustedRight - rightWidth,
    adjustedRect.origin.y + yOffset, rightWidth, DefaultSliderBarHeight),
        centerRect  = NSMakeRect(leftRect.origin.x +
    leftRect.size.width, adjustedRect.origin.y + yOffset, centerWidth,
    DefaultSliderBarHeight);

    minXOrigin = 10;
    maxXOrigin = adjustedRight;

    [gSliderTrackLeft drawInRect: leftRect
        fromRect: NSZeroRect
        operation: NSCompositeSourceOver
        fraction: 1.0];

    [gSliderTrackCenter drawInRect: centerRect
        fromRect: NSZeroRect
        operation: NSCompositeSourceOver
        fraction: 1.0];

    [gSliderTrackRight drawInRect: rightRect
        fromRect: NSZeroRect
        operation: NSCompositeSourceOver
        fraction: 1.0];
    }
  • Hi Ken

    Check out this link for a solution and description of your problem.

    http://www.cocoabuilder.com/archive/message/cocoa/2007/1/16/177288

    Cheers,
    Micke

    On Mar 17, 2007, at 9:01 PM, Ken Tozier wrote:

    > Hi
    >
    > I wrote a custom NSSlider and NSSliderCell, overrode the "drawKnob:"
    > and "drawBarInside:flipped:" of the NSSliderCell and got the stuff I
    > want to draw working correctly, but I'm still getting the default
    > slider bar behind my slider bar. I intentionally don't call the
    > NSSliderCell's superclass which I thought would do the trick,  but
    > no luck. How can I get rid of the default?
    >
    > Thanks for any help
    >
    > Ken
    >
    > Here's the slider bar draw method
    >
    > - (void) drawBarInside:(NSRect) inRect
    > flipped:(BOOL) inFlipped
    > {
    > NSRect        adjustedRect        = NSMakeRect(inRect.origin.x +
    > 10, 0, inRect.size.width - 20, inRect.size.height);
    >
    > float        rectHeight            = inRect.size.height,
    > leftWidth            = [gSliderTrackLeft size].width,
    > rightWidth            = [gSliderTrackRight size].width,
    > centerWidth            = adjustedRect.size.width -
    > leftWidth - rightWidth,
    > adjustedRight        = adjustedRect.origin.x +
    > adjustedRect.size.width,
    > yOffset                = (rectHeight -
    > DefaultSliderBarHeight) / 2;
    >
    > NSRect        leftRect            =
    > NSMakeRect(adjustedRect.origin.x, adjustedRect.origin.y + yOffset,
    > leftWidth, DefaultSliderBarHeight),
    > rightRect            = NSMakeRect(adjustedRight -
    > rightWidth, adjustedRect.origin.y + yOffset, rightWidth,
    > DefaultSliderBarHeight),
    > centerRect            = NSMakeRect(leftRect.origin.x
    > + leftRect.size.width, adjustedRect.origin.y + yOffset, centerWidth,
    > DefaultSliderBarHeight);
    >
    > minXOrigin    = 10;
    > maxXOrigin    = adjustedRight;
    >
    > [gSliderTrackLeft drawInRect: leftRect
    > fromRect: NSZeroRect
    > operation: NSCompositeSourceOver
    > fraction: 1.0];
    >
    > [gSliderTrackCenter drawInRect: centerRect
    > fromRect: NSZeroRect
    > operation: NSCompositeSourceOver
    > fraction: 1.0];
    >
    > [gSliderTrackRight drawInRect: rightRect
    > fromRect: NSZeroRect
    > operation: NSCompositeSourceOver
    > fraction: 1.0];
    > }
  • Thanks Micke that works

    It seems really dumb though that Apple doesn't expose "- (BOOL)
    _usesCustomTrackImage" It's a very elegant way to override drawing of
    the default track bar. The alternative from that link (By Dominik Pich)

    - (void) drawWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
    {
        cellFrame = [self drawingRectForBounds: cellFrame];

        [super setTrackRect: cellFrame]; //need to access private member

        [self drawBarInside: cellFrame flipped: [controlView isFlipped]];
        [self drawKnob];
    }

    @interface NSSliderCell (SetTrackRect)
    @end

    @implementation NSSliderCell (SetTrackRect)

    - (void) setTrackRect: (NSRect)theRect {
        _trackRect = theRect;
    }

    @end

    May work but why force developers to write all that override code
    when they could just use "_usesCustomTrackImage"?

    I can't think of a single good reason to hide this method. Apple
    overrides sliders all the time in their own apps. Why make it such a
    headache for everyone else?
    /rant

    -Ken

    On Mar 17, 2007, at 4:16 PM, Mikael Gransell wrote:

    > Hi Ken
    >
    > Check out this link for a solution and description of your problem.
    >
    > http://www.cocoabuilder.com/archive/message/cocoa/2007/1/16/177288
    >
    > Cheers,
    > Micke
    >
    >
    > On Mar 17, 2007, at 9:01 PM, Ken Tozier wrote:
    >
    >> Hi
    >>
    >> I wrote a custom NSSlider and NSSliderCell, overrode the
    >> "drawKnob:" and "drawBarInside:flipped:" of the NSSliderCell and
    >> got the stuff I want to draw working correctly, but I'm still
    >> getting the default slider bar behind my slider bar. I
    >> intentionally don't call the NSSliderCell's superclass which I
    >> thought would do the trick,  but no luck. How can I get rid of the
    >> default?
    >>
    >> Thanks for any help
    >>
    >> Ken
    >>
    >> Here's the slider bar draw method
    >>
    >> - (void) drawBarInside:(NSRect) inRect
    >> flipped:(BOOL) inFlipped
    >> {
    >> NSRect        adjustedRect        = NSMakeRect(inRect.origin.x
    >> + 10, 0, inRect.size.width - 20, inRect.size.height);
    >>
    >> float        rectHeight            = inRect.size.height,
    >> leftWidth            = [gSliderTrackLeft size].width,
    >> rightWidth            = [gSliderTrackRight
    >> size].width,
    >> centerWidth            = adjustedRect.size.width -
    >> leftWidth - rightWidth,
    >> adjustedRight        = adjustedRect.origin.x +
    >> adjustedRect.size.width,
    >> yOffset                = (rectHeight -
    >> DefaultSliderBarHeight) / 2;
    >>
    >> NSRect        leftRect            = NSMakeRect
    >> (adjustedRect.origin.x, adjustedRect.origin.y + yOffset,
    >> leftWidth, DefaultSliderBarHeight),
    >> rightRect            = NSMakeRect(adjustedRight -
    >> rightWidth, adjustedRect.origin.y + yOffset, rightWidth,
    >> DefaultSliderBarHeight),
    >> centerRect            = NSMakeRect
    >> (leftRect.origin.x + leftRect.size.width, adjustedRect.origin.y +
    >> yOffset, centerWidth, DefaultSliderBarHeight);
    >>
    >> minXOrigin    = 10;
    >> maxXOrigin    = adjustedRight;
    >>
    >> [gSliderTrackLeft drawInRect: leftRect
    >> fromRect: NSZeroRect
    >> operation: NSCompositeSourceOver
    >> fraction: 1.0];
    >>
    >> [gSliderTrackCenter drawInRect: centerRect
    >> fromRect: NSZeroRect
    >> operation: NSCompositeSourceOver
    >> fraction: 1.0];
    >>
    >> [gSliderTrackRight drawInRect: rightRect
    >> fromRect: NSZeroRect
    >> operation: NSCompositeSourceOver
    >> fraction: 1.0];
    >> }
    >
  • I feel that the main problem here is that the name of that method and
    the documentation can easily be misinterpreted since they do their
    drawing somewhere else.  In other words, the method -
    (BOOL)_usesCustomTrackImage should not need to be there.

    /Micke

    On Mar 17, 2007, at 11:10 PM, Ken Tozier wrote:

    > Thanks Micke that works
    >
    > It seems really dumb though that Apple doesn't expose "-
    > (BOOL)_usesCustomTrackImage" It's a very elegant way to override
    > drawing of the default track bar. The alternative from that link (By
    > Dominik Pich)
    >
    > - (void) drawWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
    > {
    > cellFrame = [self drawingRectForBounds: cellFrame];
    >
    > [super setTrackRect: cellFrame]; //need to access private member
    >
    > [self drawBarInside: cellFrame flipped: [controlView isFlipped]];
    > [self drawKnob];
    > }
    >
    > @interface NSSliderCell (SetTrackRect)
    > @end
    >
    > @implementation NSSliderCell (SetTrackRect)
    >
    > - (void) setTrackRect: (NSRect)theRect {
    > _trackRect = theRect;
    > }
    >
    > @end
    >
    >
    > May work but why force developers to write all that override code
    > when they could just use "_usesCustomTrackImage"?
    >
    > I can't think of a single good reason to hide this method. Apple
    > overrides sliders all the time in their own apps. Why make it such a
    > headache for everyone else?
    > /rant
    >
    > -Ken
    >
    >
    > On Mar 17, 2007, at 4:16 PM, Mikael Gransell wrote:
    >
    >> Hi Ken
    >>
    >> Check out this link for a solution and description of your problem.
    >>
    >> http://www.cocoabuilder.com/archive/message/cocoa/2007/1/16/177288
    >>
    >> Cheers,
    >> Micke
    >>
    >>
    >> On Mar 17, 2007, at 9:01 PM, Ken Tozier wrote:
    >>
    >>
    >>> Hi
    >>
    >>>
    >>
    >>> I wrote a custom NSSlider and NSSliderCell, overrode the
    >>> "drawKnob:" and "drawBarInside:flipped:" of the NSSliderCell and
    >>> got the stuff I want to draw working correctly, but I'm still
    >>> getting the default slider bar behind my slider bar. I
    >>> intentionally don't call the NSSliderCell's superclass which I
    >>> thought would do the trick,  but no luck. How can I get rid of the
    >>> default?
    >>
    >>>
    >>
    >>> Thanks for any help
    >>
    >>>
    >>
    >>> Ken
    >>
    >>>
    >>
    >>> Here's the slider bar draw method
    >>
    >>>
    >>
    >>> - (void) drawBarInside:(NSRect) inRect
    >>
    >>> flipped:(BOOL) inFlipped
    >>
    >>> {
    >>
    >>> NSRect        adjustedRect        = NSMakeRect(inRect.origin.x +
    >>> 10, 0, inRect.size.width - 20, inRect.size.height);
    >>
    >>>
    >>
    >>> float        rectHeight            = inRect.size.height,
    >>
    >>> leftWidth            = [gSliderTrackLeft size].width,
    >>
    >>> rightWidth            = [gSliderTrackRight
    >>> size].width,
    >>
    >>> centerWidth            = adjustedRect.size.width -
    >>> leftWidth - rightWidth,
    >>
    >>> adjustedRight        = adjustedRect.origin.x +
    >>> adjustedRect.size.width,
    >>
    >>> yOffset                = (rectHeight -
    >>> DefaultSliderBarHeight) / 2;
    >>
    >>>
    >>
    >>> NSRect        leftRect            =
    >>> NSMakeRect(adjustedRect.origin.x, adjustedRect.origin.y + yOffset,
    >>> leftWidth, DefaultSliderBarHeight),
    >>
    >>> rightRect            = NSMakeRect(adjustedRight -
    >>> rightWidth, adjustedRect.origin.y + yOffset, rightWidth,
    >>> DefaultSliderBarHeight),
    >>
    >>> centerRect            = NSMakeRect(leftRect.origin.x
    >>> + leftRect.size.width, adjustedRect.origin.y + yOffset,
    >>> centerWidth, DefaultSliderBarHeight);
    >>
    >>>
    >>
    >>> minXOrigin    = 10;
    >>
    >>> maxXOrigin    = adjustedRight;
    >>
    >>>
    >>
    >>> [gSliderTrackLeft drawInRect: leftRect
    >>
    >>> fromRect: NSZeroRect
    >>
    >>> operation: NSCompositeSourceOver
    >>
    >>> fraction: 1.0];
    >>
    >>>
    >>
    >>> [gSliderTrackCenter drawInRect: centerRect
    >>
    >>> fromRect: NSZeroRect
    >>
    >>> operation: NSCompositeSourceOver
    >>
    >>> fraction: 1.0];
    >>
    >>>
    >>
    >>> [gSliderTrackRight drawInRect: rightRect
    >>
    >>> fromRect: NSZeroRect
    >>
    >>> operation: NSCompositeSourceOver
    >>
    >>> fraction: 1.0];
    >>
    >>> }
    >>
    >>>
    >>

    >>

  • Oy.

    After 3 more hours of futzing, I can't get the knob to center on the
    slider bar without leaving part of itself behind when it moves.
    Anyone see what I'm doing wrong here?

    Here's the draw knob method:

    - (void) drawKnob:(NSRect) knobRect
    {
    float  adjustedLeft  = knobRect.origin.x,
      knobWidth  = knobRect.size.width,
      knobHeight  = knobRect.size.height,
      maxRight  = maxXOrigin - knobWidth;

    if ((adjustedLeft) < 10)
      adjustedLeft = 10;
    else if (adjustedLeft > maxRight)
      adjustedLeft = maxRight;

    adjustedKnobRect  = NSMakeRect(adjustedLeft, knobRect.origin.y,
    knobWidth, knobHeight);

    // following line centers the knob correctly,
    // but when you drag it, half of the pixels are
    // left behind
    /*if (isFlipped)
      adjustedRect.origin.y += 4;*/

    [gSliderKnob drawInRect: adjustedKnobRect
        fromRect: NSZeroRect
        operation: NSCompositeSourceOver
        fraction: 1.0];
    }

    And here's the other draw stuff in case that sheds light on the problem

    - (void) drawBarInside:(NSRect) inRect
        flipped:(BOOL) inFlipped
    {
    // may need this for knob drawing
    isFlipped  = inFlipped;

    // update the rectangles for the slider rail
    [self updateGeometryWithFrame: inRect];

    // draw control images
    [gSliderBackgroundImage drawInRect: inRect
        fromRect: NSZeroRect
        operation: NSCompositeSourceOver
        fraction: 1.0];

    [gSliderTrackLeft drawInRect: leftRect
        fromRect: NSZeroRect
        operation: NSCompositeSourceOver
        fraction: 1.0];

    [gSliderTrackCenter drawInRect: middleRect
        fromRect: NSZeroRect
        operation: NSCompositeSourceOver
        fraction: 1.0];

    [gSliderTrackRight drawInRect: rightRect
        fromRect: NSZeroRect
        operation: NSCompositeSourceOver
        fraction: 1.0];

    [self drawKnob];
    }

    - (void) updateGeometryWithFrame:(NSRect) inFrame
    {
    adjustedSliderRect = NSMakeRect(inFrame.origin.x + 10, 0,
    inFrame.size.width - 20, inFrame.size.height);

    float  rectHeight  = inFrame.size.height,
        leftWidth  = [gSliderTrackLeft size].width,
        rightWidth  = [gSliderTrackRight size].width,
        centerWidth  = adjustedSliderRect.size.width - leftWidth -
    rightWidth,
        yOffset  = (rectHeight - DefaultSliderBarHeight) / 2;

    adjustedRight  = adjustedSliderRect.origin.x +
    adjustedSliderRect.size.width;
    leftRect  = NSMakeRect(adjustedSliderRect.origin.x, yOffset,
    leftWidth, DefaultSliderBarHeight);
    rightRect  = NSMakeRect(adjustedRight - rightWidth, yOffset,
    rightWidth, DefaultSliderBarHeight);
    middleRect  = NSMakeRect(leftRect.origin.x + leftRect.size.width,
    yOffset, centerWidth, DefaultSliderBarHeight);

    minXOrigin  = 10;
    maxXOrigin  = adjustedRight;
    }

    - (BOOL)_usesCustomTrackImage
    {
        return YES;
    }
  • Where does it leave parts of it behind? One the top and bottom of the
    scroller or all over?

    On Mar 18, 2007, at 5:03 AM, Ken Tozier wrote:

    > Oy.
    >
    > After 3 more hours of futzing, I can't get the knob to center on the
    > slider bar without leaving part of itself behind when it moves.
    > Anyone see what I'm doing wrong here?
    >
    > Here's the draw knob method:
    >
    > - (void) drawKnob:(NSRect) knobRect
    > {
    > float        adjustedLeft        = knobRect.origin.x,
    > knobWidth        = knobRect.size.width,
    > knobHeight        = knobRect.size.height,
    > maxRight            = maxXOrigin - knobWidth;
    >
    > if ((adjustedLeft) < 10)
    > adjustedLeft    = 10;
    > else if (adjustedLeft > maxRight)
    > adjustedLeft    = maxRight;
    >
    > adjustedKnobRect            = NSMakeRect(adjustedLeft,
    > knobRect.origin.y, knobWidth, knobHeight);
    >
    > // following line centers the knob correctly,
    > // but when you drag it, half of the pixels are
    > // left behind
    > /*if (isFlipped)
    > adjustedRect.origin.y += 4;*/
    >
    > [gSliderKnob drawInRect: adjustedKnobRect
    > fromRect: NSZeroRect
    > operation: NSCompositeSourceOver
    > fraction: 1.0];
    > }
    >
    >
    > And here's the other draw stuff in case that sheds light on the
    > problem
    >
    > - (void) drawBarInside:(NSRect) inRect
    > flipped:(BOOL) inFlipped
    > {
    > // may need this for knob drawing
    > isFlipped            = inFlipped;
    >
    > // update the rectangles for the slider rail
    > [self updateGeometryWithFrame: inRect];
    >
    > // draw control images
    > [gSliderBackgroundImage drawInRect: inRect
    > fromRect: NSZeroRect
    > operation: NSCompositeSourceOver
    > fraction: 1.0];
    >
    > [gSliderTrackLeft drawInRect: leftRect
    > fromRect: NSZeroRect
    > operation: NSCompositeSourceOver
    > fraction: 1.0];
    >
    > [gSliderTrackCenter drawInRect: middleRect
    > fromRect: NSZeroRect
    > operation: NSCompositeSourceOver
    > fraction: 1.0];
    >
    > [gSliderTrackRight drawInRect: rightRect
    > fromRect: NSZeroRect
    > operation: NSCompositeSourceOver
    > fraction: 1.0];
    >
    > [self drawKnob];
    > }
    >
    > - (void) updateGeometryWithFrame:(NSRect) inFrame
    > {
    > adjustedSliderRect    = NSMakeRect(inFrame.origin.x + 10, 0,
    > inFrame.size.width - 20, inFrame.size.height);
    >
    > float            rectHeight        = inFrame.size.height,
    > leftWidth            = [gSliderTrackLeft size].width,
    > rightWidth            = [gSliderTrackRight size].width,
    > centerWidth        = adjustedSliderRect.size.width -
    > leftWidth - rightWidth,
    > yOffset            = (rectHeight -
    > DefaultSliderBarHeight) / 2;
    >
    > adjustedRight        = adjustedSliderRect.origin.x +
    > adjustedSliderRect.size.width;
    > leftRect            = NSMakeRect(adjustedSliderRect.origin.x,
    > yOffset, leftWidth, DefaultSliderBarHeight);
    > rightRect            = NSMakeRect(adjustedRight - rightWidth,
    > yOffset, rightWidth, DefaultSliderBarHeight);
    > middleRect        = NSMakeRect(leftRect.origin.x +
    > leftRect.size.width, yOffset, centerWidth, DefaultSliderBarHeight);
    >
    > minXOrigin        = 10;
    > maxXOrigin        = adjustedRight;
    > }
    >
    > - (BOOL)_usesCustomTrackImage
    > {
    > return YES;
    > }
  • On Mar 18, 2007, at 4:35 AM, Mikael Gransell wrote:

    > Where does it leave parts of it behind? One the top and bottom of
    > the scroller or all over?

    The part that extends below the bottom edge of the slider track.
    Approximately the bottom third of the knob. If you resize the view it
    refreshes but if you drag the knob again, same deal.

    >
    >
    > On Mar 18, 2007, at 5:03 AM, Ken Tozier wrote:
    >
    >> Oy.
    >>
    >> After 3 more hours of futzing, I can't get the knob to center on
    >> the slider bar without leaving part of itself behind when it
    >> moves. Anyone see what I'm doing wrong here?
    >>
    >> Here's the draw knob method:
    >>
    >> - (void) drawKnob:(NSRect) knobRect
    >> {
    >> float        adjustedLeft        = knobRect.origin.x,
    >> knobWidth        = knobRect.size.width,
    >> knobHeight        = knobRect.size.height,
    >> maxRight            = maxXOrigin - knobWidth;
    >>
    >> if ((adjustedLeft) < 10)
    >> adjustedLeft    = 10;
    >> else if (adjustedLeft > maxRight)
    >> adjustedLeft    = maxRight;
    >>
    >> adjustedKnobRect            = NSMakeRect(adjustedLeft,
    >> knobRect.origin.y, knobWidth, knobHeight);
    >>
    >> // following line centers the knob correctly,
    >> // but when you drag it, half of the pixels are
    >> // left behind
    >> /*if (isFlipped)
    >> adjustedRect.origin.y += 4;*/
    >>
    >> [gSliderKnob drawInRect: adjustedKnobRect
    >> fromRect: NSZeroRect
    >> operation: NSCompositeSourceOver
    >> fraction: 1.0];
    >> }
    >>
    >>
    >> And here's the other draw stuff in case that sheds light on the
    >> problem
    >>
    >> - (void) drawBarInside:(NSRect) inRect
    >> flipped:(BOOL) inFlipped
    >> {
    >> // may need this for knob drawing
    >> isFlipped            = inFlipped;
    >>
    >> // update the rectangles for the slider rail
    >> [self updateGeometryWithFrame: inRect];
    >>
    >> // draw control images
    >> [gSliderBackgroundImage drawInRect: inRect
    >> fromRect: NSZeroRect
    >> operation: NSCompositeSourceOver
    >> fraction: 1.0];
    >>
    >> [gSliderTrackLeft drawInRect: leftRect
    >> fromRect: NSZeroRect
    >> operation: NSCompositeSourceOver
    >> fraction: 1.0];
    >>
    >> [gSliderTrackCenter drawInRect: middleRect
    >> fromRect: NSZeroRect
    >> operation: NSCompositeSourceOver
    >> fraction: 1.0];
    >>
    >> [gSliderTrackRight drawInRect: rightRect
    >> fromRect: NSZeroRect
    >> operation: NSCompositeSourceOver
    >> fraction: 1.0];
    >>
    >> [self drawKnob];
    >> }
    >>
    >> - (void) updateGeometryWithFrame:(NSRect) inFrame
    >> {
    >> adjustedSliderRect    = NSMakeRect(inFrame.origin.x + 10, 0,
    >> inFrame.size.width - 20, inFrame.size.height);
    >>
    >> float            rectHeight        = inFrame.size.height,
    >> leftWidth            = [gSliderTrackLeft size].width,
    >> rightWidth            = [gSliderTrackRight
    >> size].width,
    >> centerWidth        = adjustedSliderRect.size.width
    >> - leftWidth - rightWidth,
    >> yOffset            = (rectHeight -
    >> DefaultSliderBarHeight) / 2;
    >>
    >> adjustedRight        = adjustedSliderRect.origin.x +
    >> adjustedSliderRect.size.width;
    >> leftRect            = NSMakeRect(adjustedSliderRect.origin.x,
    >> yOffset, leftWidth, DefaultSliderBarHeight);
    >> rightRect            = NSMakeRect(adjustedRight - rightWidth,
    >> yOffset, rightWidth, DefaultSliderBarHeight);
    >> middleRect        = NSMakeRect(leftRect.origin.x +
    >> leftRect.size.width, yOffset, centerWidth, DefaultSliderBarHeight);
    >>
    >> minXOrigin        = 10;
    >> maxXOrigin        = adjustedRight;
    >> }
    >>
    >> - (BOOL)_usesCustomTrackImage
    >> {
    >> return YES;
    >> }

  • Don't override the private _usesCustomTrackImage: method. Instead,
    override -[NSSliderCell drawWithFrame:inView:] and call your -
    drawBarInside:flipped: and -drawKnob: methods inside that. You'll
    have to do calculations for framing, positioning, etc., but they're
    not hard.

    In the end, this may actually solve your problem, as well, because
    you'll have full control over what's drawn where. You can redraw
    dirty areas as you see fit, or summarily redraw the entire bar at
    once if it's not a performance issue.

    This is what I do in Think's custom slider, and it works quite well.

    --
    m-s

    On 18 Mar, 2007, at 04:38, Ken Tozier wrote:

    >
    > On Mar 18, 2007, at 4:35 AM, Mikael Gransell wrote:
    >
    >> Where does it leave parts of it behind? One the top and bottom of
    >> the scroller or all over?
    >
    > The part that extends below the bottom edge of the slider track.
    > Approximately the bottom third of the knob. If you resize the view
    > it refreshes but if you drag the knob again, same deal.
    >
    >>
    >>
    >> On Mar 18, 2007, at 5:03 AM, Ken Tozier wrote:
    >>
    >>> Oy.
    >>>
    >>> After 3 more hours of futzing, I can't get the knob to center on
    >>> the slider bar without leaving part of itself behind when it
    >>> moves. Anyone see what I'm doing wrong here?
    >>>
    >>> Here's the draw knob method:
    >>>
    >>> - (void) drawKnob:(NSRect) knobRect
    >>> {
    >>> float        adjustedLeft        = knobRect.origin.x,
    >>> knobWidth        = knobRect.size.width,
    >>> knobHeight        = knobRect.size.height,
    >>> maxRight            = maxXOrigin - knobWidth;
    >>>
    >>> if ((adjustedLeft) < 10)
    >>> adjustedLeft    = 10;
    >>> else if (adjustedLeft > maxRight)
    >>> adjustedLeft    = maxRight;
    >>>
    >>> adjustedKnobRect            = NSMakeRect(adjustedLeft,
    >>> knobRect.origin.y, knobWidth, knobHeight);
    >>>
    >>> // following line centers the knob correctly,
    >>> // but when you drag it, half of the pixels are
    >>> // left behind
    >>> /*if (isFlipped)
    >>> adjustedRect.origin.y += 4;*/
    >>>
    >>> [gSliderKnob drawInRect: adjustedKnobRect
    >>> fromRect: NSZeroRect
    >>> operation: NSCompositeSourceOver
    >>> fraction: 1.0];
    >>> }
    >>>
    >>>
    >>> And here's the other draw stuff in case that sheds light on the
    >>> problem
    >>>
    >>> - (void) drawBarInside:(NSRect) inRect
    >>> flipped:(BOOL) inFlipped
    >>> {
    >>> // may need this for knob drawing
    >>> isFlipped            = inFlipped;
    >>>
    >>> // update the rectangles for the slider rail
    >>> [self updateGeometryWithFrame: inRect];
    >>>
    >>> // draw control images
    >>> [gSliderBackgroundImage drawInRect: inRect
    >>> fromRect: NSZeroRect
    >>> operation: NSCompositeSourceOver
    >>> fraction: 1.0];
    >>>
    >>> [gSliderTrackLeft drawInRect: leftRect
    >>> fromRect: NSZeroRect
    >>> operation: NSCompositeSourceOver
    >>> fraction: 1.0];
    >>>
    >>> [gSliderTrackCenter drawInRect: middleRect
    >>> fromRect: NSZeroRect
    >>> operation: NSCompositeSourceOver
    >>> fraction: 1.0];
    >>>
    >>> [gSliderTrackRight drawInRect: rightRect
    >>> fromRect: NSZeroRect
    >>> operation: NSCompositeSourceOver
    >>> fraction: 1.0];
    >>>
    >>> [self drawKnob];
    >>> }
    >>>
    >>> - (void) updateGeometryWithFrame:(NSRect) inFrame
    >>> {
    >>> adjustedSliderRect    = NSMakeRect(inFrame.origin.x + 10, 0,
    >>> inFrame.size.width - 20, inFrame.size.height);
    >>>
    >>> float            rectHeight        = inFrame.size.height,
    >>> leftWidth            = [gSliderTrackLeft size].width,
    >>> rightWidth            = [gSliderTrackRight
    >>> size].width,
    >>> centerWidth        = adjustedSliderRect.size.width
    >>> - leftWidth - rightWidth,
    >>> yOffset            = (rectHeight -
    >>> DefaultSliderBarHeight) / 2;
    >>>
    >>> adjustedRight        = adjustedSliderRect.origin.x +
    >>> adjustedSliderRect.size.width;
    >>> leftRect            = NSMakeRect(adjustedSliderRect.origin.x,
    >>> yOffset, leftWidth, DefaultSliderBarHeight);
    >>> rightRect            = NSMakeRect(adjustedRight - rightWidth,
    >>> yOffset, rightWidth, DefaultSliderBarHeight);
    >>> middleRect        = NSMakeRect(leftRect.origin.x +
    >>> leftRect.size.width, yOffset, centerWidth, DefaultSliderBarHeight);
    >>>
    >>> minXOrigin        = 10;
    >>> maxXOrigin        = adjustedRight;
    >>> }
    >>>
    >>> - (BOOL)_usesCustomTrackImage
    >>> {
    >>> return YES;
    >>> }


  • Sorry, this is an NSCell method, not NSSliderCell specifically. :-)

    --
    m-s

    On 18 Mar, 2007, at 04:59, Michael Watson wrote:

    > -[NSSliderCell drawWithFrame:inView:]