Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSSlider NSSliderCell clipping custom knob

I am creating a custom NSSlider with a custom NSSliderCell. All is working beautifully, other than the knob. When I drag it to the max value the knob is being clipped, I can only see 50% of the knob image.

When assigning my custom NSSliderCell I am setting the knobThickness to the width of the image I am using as the knob. I assumed (I guess wrongly) that it would take that into account and stop it from clipping?

Any ideas what I am doing wrong? The slider is hitting the maxValue only when the knob is clipped at 50%, so its not travelling without adding any value.

- (void)drawKnob:(NSRect)knobRect {
 NSImage * knob = _knobOff;
 knobRectVar = knobRect;

 [[self controlView] lockFocus];
 [knob
  compositeToPoint:
  NSMakePoint(knobRect.origin.x+4,knobRect.origin.y+knobRect.size.height+20)
  operation:NSCompositeSourceOver];
 [[self controlView] unlockFocus];
}

- (void)drawBarInside:(NSRect)rect flipped:(BOOL)flipped {
 rect.size.height = 8;

 [[self controlView] lockFocus];
 NSImage *leftCurve = [NSImage imageNamed:@"customSliderLeft"];
 [leftCurve drawInRect:NSMakeRect(5, 25, 8, 8) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];

    NSRect leftRect = rect;
    leftRect.origin.x=13;
    leftRect.origin.y=25;
    leftRect.size.width = knobRectVar.origin.x + (knobRectVar.size.width/2);
    [leftBarImage setSize:leftRect.size];
    [leftBarImage drawInRect:leftRect fromRect: NSZeroRect operation: NSCompositeSourceOver fraction:1];
 [[self controlView] unlockFocus];

}
like image 611
mootymoots Avatar asked Oct 13 '22 17:10

mootymoots


2 Answers

The NSSLider expects a special sizes off the knob images for each control size:

NSRegularControlSize:   21x21
NSSmallControlSize:     15x15
NSMiniControlSize:      12x12

Unfortunately the height of your knob image mustn't exceed one of this parameters. But it's width may be longer. If it is you may count an x position for the knob like this:

CGFloat newOriginX = knobRect.origin.x *
        (_barRect.size.width - (_knobImage.size.width - knobRect.size.width)) / _barRect.size.width;

Where _barRect is a cellFrame of your bar background from:

- (void)drawBarInside:(NSRect)cellFrame flipped:(BOOL)flipped;

I've created a simple solution for the custom NSSlider. Follow this link https://github.com/Doshipak/LADSlider

like image 109
Doshipak Avatar answered Oct 18 '22 04:10

Doshipak


You can override [NSSliderCell knobRectFlipped:] in addition to [NSSliderCell drawKnob:]. Here is my solution:

- (void)drawKnob:(NSRect)rect
{
  NSImage *drawImage = [self knobImage];

  NSRect drawRect = [self knobRectFlipped:[self.controlView isFlipped]];

  CGFloat fraction = 1.0;

  [drawImage drawInRect:drawRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:fraction respectFlipped:YES hints:nil];
}

- (NSRect)knobRectFlipped:(BOOL)flipped
{
  NSImage *drawImage = [self knobImage];

  NSRect drawRect = [super knobRectFlipped:flipped];

  drawRect.size = drawImage.size;

  NSRect bounds = self.controlView.bounds;
  bounds = NSInsetRect(bounds, ceil(drawRect.size.width / 2), 0);
  CGFloat val = MIN(self.maxValue, MAX(self.minValue, self.doubleValue));
  val = (val - self.minValue) / (self.maxValue - self.minValue);
  CGFloat x = val * NSWidth(bounds) + NSMinX(bounds);

  drawRect = NSOffsetRect(drawRect, x - NSMidX(drawRect) + 1, 0);
  return drawRect;
}
like image 39
Yoav Avatar answered Oct 18 '22 04:10

Yoav