0

I am using NSScroller in cocoa app. NSScroller is translucent in mojave dark mode but in looks fine in mojave light mode.

I have tried subclassing nsscroller and try to change background color. it changes background color but translucent effect is not disappearing.

class CustomScroller: NSScroller {
- (void)drawRect:(NSRect)dirtyRect {

        NSColor.red.set()
        __NSRectFill(dirtyRect)
        self.drawKnob()
  }
}
Muhammad
  • 23
  • 1
  • 6

1 Answers1

0

Maybe add this to your CustomScroller?

- (BOOL) isOpaque {return YES;}

The venerable BGHUDAppKit provides an example of how to draw your own themes from scratch.
Most people hate it because its an unmaintainable mess. Despite this, I've kept my own version up to date for years :)

You'll need your own 'theme' implementation. For example [[[self theme] scrollerStroke] set]; needs to return an NSColor. A good rule of thumb for UI themes:

  • the 10% rule The human eye can distinguish easily between brightness differences of 10%, so for example the scroll bar should be outlined with a color that is 10% brighter than the fill color. ( outline with 57.0/255.0, fill with 50.0/255.0 )

  • try to use grayscale colors as much as possible.

Here's my implementation, with notes included for various OS versions:

//
//  BGHudScroller.m
//  HUDScroller
//
//  Created by BinaryGod on 5/22/08.
//
//  Copyright (c) 2008, Tim Davis (BinaryMethod.com, binary.god@gmail.com)
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met:
//
//      Redistributions of source code must retain the above copyright notice, this
//  list of conditions and the following disclaimer.
//
//      Redistributions in binary form must reproduce the above copyright notice,
//  this list of conditions and the following disclaimer in the documentation and/or
//  other materials provided with the distribution.
//
//      Neither the name of the BinaryMethod.com nor the names of its contributors
//  may be used to endorse or promote products derived from this software without
//  specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
//  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
//  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
//  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
//  POSSIBILITY OF SUCH DAMAGE.

// Special thanks to Matt Gemmell (http://mattgemmell.com/) for helping me solve the
// transparent drawing issues.  Your awesome man!!!

#import "BGHUDScroller.h"
#import "BGThemeMbox.h" // need implementation specific stuff

@implementation BGHUDScroller

#pragma mark Drawing Functions

@synthesize themeKey;
@synthesize LayerKey;

-(id)init {

    self = [super init];

    if(self) {

        self.themeKey = @"gradientTheme";
    }

    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder {

    self = [super initWithCoder: aDecoder];

    if(self) {

        if([aDecoder containsValueForKey: @"themeKey"]) {

            self.themeKey = [aDecoder decodeObjectForKey: @"themeKey"];
        } else {
            self.themeKey = @"gradientTheme";
        }
    }

    return self;
}

-(void)encodeWithCoder: (NSCoder *)coder {

    [super encodeWithCoder: coder];

    [coder encodeObject: self.themeKey forKey: @"themeKey"];
}

- (BGTheme *)theme
{
   NSWindow *window = [self window];
   if ( [window isPanel] )
      return [[BGThemeManager keyedManager] themeForKey: @"flatTheme"];
   else
      return [[BGThemeManager keyedManager] themeForKey: [[self target] themeKey]];
}

- (BOOL) preservesContentDuringLiveResize { return YES; }
- (void) setFrameSize:(NSSize)newSize
{
   [super setFrameSize:newSize];

   // A change in size has required the view to be invalidated.
   if ([self inLiveResize])
   {
      NSRect rects[4];
      NSInteger count;
      [self getRectsExposedDuringLiveResize:rects count:&count];
      while (count-- > 0)
      {
         [self setNeedsDisplayInRect:rects[count]];
      }
   }
   else
   {
      [self setNeedsDisplay:YES];
   }
}

- (BOOL) isOpaque {return YES;}
- (void)drawRect:(NSRect)rect {
   waitIfNeeded(self);  

   static SInt32 maj, min, patch;
   if (!maj)
   {
      Gestalt(gestaltSystemVersionMajor, &maj);
      Gestalt(gestaltSystemVersionMinor, &min);
      Gestalt(gestaltSystemVersionBugFix, &patch);
   }

//  if ( sOSVersion >= 0x1070 )
//   {
//       // Lion deprecated scroller arrows altogether, so just let super call my
//      // overrides for drawKnobSlotInRect and drawKnob
//      printf( "drawRect: x%0.2f w %0.2f h %0.2f\n", rect.origin.x, rect.size.width, rect.size.height );
//      [super drawRect:[self bounds]];
//      return;
//   }

   if ( maj == 10 && min < 7 )
   {
      //////////////////////// BEGIN  PRE-LION VERSION ////////////////////////////
      arrowPosition = [[[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain] valueForKey: @"AppleScrollBarVariant"];

      if(arrowPosition == nil) {

         arrowPosition = @"DoubleMax";
      }
      //////////////////////// END  PRE-LION VERSION ////////////////////////////   
    }

    //NSDisableScreenUpdates();

//  [[NSColor headerFillColor] set];
//  NSRectFill([self bounds]);

    // Draw knob-slot.
    [self drawKnobSlotInRect: [self bounds] highlight: YES];

   if (( maj == 10 && min < 7) || ( [self usableParts] != 0 && [self knobProportion] < 1.0 ))
   {
      // Draw knob
      [self drawKnob];
   }

   if ( maj == 10 && min < 7) // PRE-LION VERSION
   {
      // kpk note: we won't get here if running lion, and it works on 10.6.8,
      // also note, drawArrow:highlight: is public API, and drawArrow:highlightPart: is private API override?
      // Draw arrows.  
      [self drawArrow: NSScrollerIncrementArrow highlight: ([self hitPart] == NSScrollerIncrementLine)];
      [self drawArrow: NSScrollerDecrementArrow highlight: ([self hitPart] == NSScrollerDecrementLine)];
    }
    //[[self window] invalidateShadow];

    //NSEnableScreenUpdates();

}

- (void)drawKnob {
   NSRect bounds = [self bounds];
   if ( bounds.size.width < 40 && bounds.size.height < 40 )
      return; // don't draw something stupid if too tiny to show... happens often during initial sizing 

   BOOL isHoriz = ( bounds.size.width > bounds.size.height );

   NSRect knobRect = [self rectForPart: NSScrollerKnob];
   //DLog( @"usable parts %d horiz %d %@ knob %@ frame %@", [self usableParts], isHoriz, NSStringFromRect( [self bounds] ), NSStringFromRect( knobRect ), NSStringFromRect( [self frame] ) );
    if( ! isHoriz ) {

        //Draw Knob
        NSBezierPath *knob = [[NSBezierPath alloc] init];


        [knob appendBezierPathWithArcWithCenter: NSMakePoint(knobRect.origin.x + ((knobRect.size.width - .5) /2), (knobRect.origin.y + ((knobRect.size.width -2) /2)))
                                         radius: (knobRect.size.width -2) /2
                                     startAngle: 180
                                       endAngle: 0];

        [knob appendBezierPathWithArcWithCenter: NSMakePoint(knobRect.origin.x + ((knobRect.size.width - .5) /2), ((knobRect.origin.y + knobRect.size.height) - ((knobRect.size.width -2) /2)))
                                         radius: (knobRect.size.width -2) /2
                                     startAngle: 0
                                       endAngle: 180];

        [[[self theme] scrollerStroke] set];
        [knob fill];

        knobRect.origin.x += 1;
        knobRect.origin.y += 1;
        knobRect.size.width -= 2;
        knobRect.size.height -= 2;

        [knob release];
        knob = [[NSBezierPath alloc] init];

        [knob appendBezierPathWithArcWithCenter: NSMakePoint(knobRect.origin.x + ((knobRect.size.width - .5) /2), (knobRect.origin.y + ((knobRect.size.width -2) /2)))
                                         radius: (knobRect.size.width -2) /2
                                     startAngle: 180
                                       endAngle: 0];

        [knob appendBezierPathWithArcWithCenter: NSMakePoint(knobRect.origin.x + ((knobRect.size.width - .5) /2), ((knobRect.origin.y + knobRect.size.height) - ((knobRect.size.width -2) /2)))
                                         radius: (knobRect.size.width -2) /2
                                     startAngle: 0
                                       endAngle: 180];

        [[[self theme] scrollerKnobGradient] drawInBezierPath: knob angle: 0];

        [knob release];
    } else {

        //Draw Knob
        NSBezierPath *knob = [[NSBezierPath alloc] init];

        [knob appendBezierPathWithArcWithCenter: NSMakePoint(knobRect.origin.x + ((knobRect.size.height - .5) /2), (knobRect.origin.y + ((knobRect.size.height -1) /2)))
                                         radius: (knobRect.size.height -1) /2
                                     startAngle: 90
                                       endAngle: 270];

        [knob appendBezierPathWithArcWithCenter: NSMakePoint((knobRect.origin.x + knobRect.size.width) - ((knobRect.size.height - .5) /2), (knobRect.origin.y + ((knobRect.size.height -1) /2)))
                                         radius: (knobRect.size.height -1) /2
                                     startAngle: 270
                                       endAngle: 90];

        [[[self theme] scrollerStroke] set];
        [knob fill];

        knobRect.origin.x += 1;
        knobRect.origin.y += 1;
        knobRect.size.width -= 2;
        knobRect.size.height -= 2;

        [knob release];
        knob = [[NSBezierPath alloc] init];

        [knob appendBezierPathWithArcWithCenter: NSMakePoint(knobRect.origin.x + ((knobRect.size.height - .5) /2), (knobRect.origin.y + ((knobRect.size.height -1) /2)))
                                         radius: (knobRect.size.height -1) /2
                                     startAngle: 90
                                       endAngle: 270];

        [knob appendBezierPathWithArcWithCenter: NSMakePoint((knobRect.origin.x + knobRect.size.width) - ((knobRect.size.height - .5) /2), (knobRect.origin.y + ((knobRect.size.height -1) /2)))
                                         radius: (knobRect.size.height -1) /2
                                     startAngle: 270
                                       endAngle: 90];

        [[[self theme] scrollerKnobGradient] drawInBezierPath: knob angle: 90];

        [knob release];
    }
}

- (void)drawArrow:(NSScrollerArrow)arrow highlightPart:(NSUInteger)part {

    if(arrow == NSScrollerDecrementArrow) {

        if(part == (NSUInteger)-1 || part == 0) {

            [self drawDecrementArrow: NO];
        } else {

            [self drawDecrementArrow: YES];
        }
    }

    if(arrow == NSScrollerIncrementArrow) {

        if(part == 1 || part == (NSUInteger)-1) {

            [self drawIncrementArrow: NO];
        } else {

            [self drawIncrementArrow: YES];
        }
    }
}

- (void)drawKnobSlotInRect:(NSRect)rect highlight:(BOOL)highlight {
   NSRect bounds = [self bounds];
   [[[self theme] sliderTrackColor] set];
   NSRectFill(bounds);

   if ( bounds.size.width < 40 && bounds.size.height < 40 )
       return; // don't draw something stupid if too tiny to show... happens often during initial sizing 

   BOOL isHoriz = ( bounds.size.width > bounds.size.height );

    if( ! isHoriz) {
        //Draw Knob Slot
        //[[[self theme] scrollerTrackGradient] drawInRect: rect angle: 0];
        if([arrowPosition isEqualToString: @"DoubleMax"]) {

            //Adjust rect height for top base
            rect.size.height = 8; // (bgWidth - 2) / 2;

            //Draw Top Base
            NSBezierPath *path = [[NSBezierPath alloc] init];
            NSPoint basePoints[4];

            [path appendBezierPathWithArcWithCenter: NSMakePoint(rect.size.width /2, rect.size.height + (rect.size.width /2) -5)
                                             radius: (rect.size.width ) /2
                                         startAngle: 180
                                           endAngle: 0];

            //Add the rest of the points
            basePoints[3] = NSMakePoint( rect.origin.x, rect.origin.y + rect.size.height);
            basePoints[2] = NSMakePoint( rect.origin.x, rect.origin.y);
            basePoints[1] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y);
            basePoints[0] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);

            [path appendBezierPathWithPoints: basePoints count: 4];

            [[[self theme] scrollerArrowNormalGradient] drawInBezierPath: path angle: 0];

            [path release];
        }
    } else {
        //Draw Knob Slot
        //[[[self theme] scrollerTrackGradient] drawInRect: rect angle: 90];
        if([arrowPosition isEqualToString: @"DoubleMax"]) {

            //Adjust rect height for top base
            rect.size.width = 8; //(bgWidth - 2) / 2;

            //Draw Top Base
            NSBezierPath *path = [[NSBezierPath alloc] init];
            NSPoint basePoints[4];

            [path appendBezierPathWithArcWithCenter: NSMakePoint((rect.size.height /2) +5, rect.origin.y + (rect.size.height /2) )
                                             radius: (rect.size.height ) /2
                                         startAngle: 90
                                           endAngle: 270];

            //Add the rest of the points
            basePoints[2] = NSMakePoint( rect.origin.x, rect.origin.y + rect.size.height);
            basePoints[1] = NSMakePoint( rect.origin.x, rect.origin.y);
            basePoints[0] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y);
            basePoints[3] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);

            [path appendBezierPathWithPoints: basePoints count: 4];

            [[[self theme] scrollerArrowNormalGradient] drawInBezierPath: path angle: 0];

            [path release];
        }
    }
}

- (void)drawDecrementArrow:(BOOL)highlighted {
   NSRect bounds = [self bounds];
   if ( bounds.size.width < 40 && bounds.size.height < 40 )
      return; // don't draw something stupid if too tiny to show... happens often during initial sizing 

   BOOL isHoriz = ( bounds.size.width > bounds.size.height );

    if( ! isHoriz) {

        if([arrowPosition isEqualToString: @"DoubleMax"]) {

            //Draw Decrement Button
            NSRect rect = [self rectForPart: NSScrollerDecrementLine];
            NSBezierPath *path = [[NSBezierPath alloc] init];
            NSPoint basePoints[4];

            //Add Notch
            [path appendBezierPathWithArcWithCenter: NSMakePoint((rect.size.width ) /2, (rect.origin.y  - ((rect.size.width ) /2) + 1))
                                             radius: (rect.size.width ) /2
                                         startAngle: 0
                                           endAngle: 180];

            //Add the rest of the points
            basePoints[0] = NSMakePoint( rect.origin.x, rect.origin.y);
            basePoints[1] = NSMakePoint( rect.origin.x, rect.origin.y + rect.size.height);
            basePoints[2] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
            basePoints[3] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y);

            //Add Points to Path
            [path appendBezierPathWithPoints: basePoints count: 4];

            //Fill Path
            if(!highlighted) {

                [[[self theme] scrollerArrowNormalGradient] drawInBezierPath: path angle: 0];
            } else {

                [[[self theme] scrollerArrowPushedGradient] drawInBezierPath: path angle: 0];
            }

            //Create Arrow Glyph
            NSBezierPath *arrow = [[NSBezierPath alloc] init];

            NSPoint points[3];
            points[0] = NSMakePoint( rect.size.width /2, rect.origin.y + (rect.size.height /2) -3);
            points[1] = NSMakePoint( (rect.size.width /2) +3.5, rect.origin.y + (rect.size.height /2) +3);
            points[2] = NSMakePoint( (rect.size.width /2) -3.5, rect.origin.y + (rect.size.height /2) +3);

            [arrow appendBezierPathWithPoints: points count: 3];

            //[[[self theme] scrollerStroke] set];
            [[[self theme] scrollerStroke] set];
            [arrow fill];

            //Create Devider Line
            [[[self theme] scrollerStroke] set];

            [NSBezierPath strokeLineFromPoint: NSMakePoint(0, (rect.origin.y + rect.size.height) +.5)
                                      toPoint: NSMakePoint(rect.size.width, (rect.origin.y + rect.size.height) +.5)];

            [path release];
            [arrow release];

        } else {

            NSRect rect = [self rectForPart: NSScrollerDecrementLine];

            NSBezierPath *path = [[NSBezierPath alloc] init];
            NSPoint basePoints[4];

            [path appendBezierPathWithArcWithCenter: NSMakePoint(rect.size.width /2, rect.size.height + (rect.size.width /2) -3)
                                             radius: (rect.size.width ) /2
                                         startAngle: 180
                                           endAngle: 0];

            //Add the rest of the points
            basePoints[3] = NSMakePoint( rect.origin.x, rect.origin.y + rect.size.height);
            basePoints[2] = NSMakePoint( rect.origin.x, rect.origin.y);
            basePoints[1] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y);
            basePoints[0] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);

            [path appendBezierPathWithPoints: basePoints count: 4];

            //Fill Path
            if(!highlighted) {

                [[[self theme] scrollerArrowNormalGradient] drawInBezierPath: path angle: 0];
            } else {

                [[[self theme] scrollerArrowPushedGradient] drawInBezierPath: path angle: 0];
            }

            //Create Arrow Glyph
            NSBezierPath *arrow = [[NSBezierPath alloc] init];

            NSPoint points[3];
            points[0] = NSMakePoint( rect.size.width /2, rect.origin.y + (rect.size.height /2) -3);
            points[1] = NSMakePoint( (rect.size.width /2) +3.5, rect.origin.y + (rect.size.height /2) +3);
            points[2] = NSMakePoint( (rect.size.width /2) -3.5, rect.origin.y + (rect.size.height /2) +3);

            [arrow appendBezierPathWithPoints: points count: 3];

            [[[self theme] scrollerStroke] set];
            [arrow fill];

            [path release];
            [arrow release];
        }
    } else {

        if([arrowPosition isEqualToString: @"DoubleMax"]) {

            //Draw Decrement Button
            NSRect rect = [self rectForPart: NSScrollerDecrementLine];
            NSBezierPath *path = [[NSBezierPath alloc] init];
            NSPoint basePoints[4];

            //Add Notch
            [path appendBezierPathWithArcWithCenter: NSMakePoint(rect.origin.x - ((rect.size.height ) /2), (rect.origin.y  + ((rect.size.height ) /2) ))
                                             radius: (rect.size.height ) /2
                                         startAngle: 270
                                           endAngle: 90];

            //Add the rest of the points
            basePoints[3] = NSMakePoint( rect.origin.x - (((rect.size.height ) /2) -1), rect.origin.y);
            basePoints[0] = NSMakePoint( rect.origin.x - (((rect.size.height ) /2) -1), rect.origin.y + rect.size.height);
            basePoints[1] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
            basePoints[2] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y);

            //Add Points to Path
            [path appendBezierPathWithPoints: basePoints count: 4];

            //Fill Path
            if(!highlighted) {

                [[[self theme] scrollerArrowNormalGradient] drawInBezierPath: path angle: 90];
            } else {

                [[[self theme] scrollerArrowPushedGradient] drawInBezierPath: path angle: 90];
            }

            //Create Arrow Glyph
            NSBezierPath *arrow = [[NSBezierPath alloc] init];

            NSPoint points[3];
            points[0] = NSMakePoint( rect.origin.x + (rect.size.width /2) -3, rect.size.height /2);
            points[1] = NSMakePoint( rect.origin.x + (rect.size.height /2) +3, (rect.size.height /2) +3.5);
            points[2] = NSMakePoint( rect.origin.x + (rect.size.height /2) +3, (rect.size.height /2) -3.5);

            [arrow appendBezierPathWithPoints: points count: 3];

            [[[self theme] scrollerStroke] set];
            [arrow fill];

            //Create Devider Line
            [[[self theme] scrollerStroke] set];

            [NSBezierPath strokeLineFromPoint: NSMakePoint(rect.origin.x + rect.size.width -.5, rect.origin.y)
                                      toPoint: NSMakePoint(rect.origin.x + rect.size.width -.5, rect.origin.y + rect.size.height)];

            [path release];
            [arrow release];

        } else {

            NSRect rect = [self rectForPart: NSScrollerDecrementLine];

            NSBezierPath *path = [[NSBezierPath alloc] init];
            NSPoint basePoints[4];

            [path appendBezierPathWithArcWithCenter: NSMakePoint(rect.origin.x + (rect.size.width -2) + ((rect.size.height ) /2), (rect.origin.y  + ((rect.size.height ) /2) ))
                                             radius: (rect.size.height ) /2
                                         startAngle: 90
                                           endAngle: 270];

            //Add the rest of the points
            basePoints[2] = NSMakePoint( rect.origin.x, rect.origin.y + rect.size.height);
            basePoints[1] = NSMakePoint( rect.origin.x, rect.origin.y);
            basePoints[0] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y);
            basePoints[3] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);

            [path appendBezierPathWithPoints: basePoints count: 4];

            //Fill Path
            if(!highlighted) {

                [[[self theme] scrollerArrowNormalGradient] drawInBezierPath: path angle: 90];
            } else {

                [[[self theme] scrollerArrowPushedGradient] drawInBezierPath: path angle: 90];
            }

            //Create Arrow Glyph
            NSBezierPath *arrow = [[NSBezierPath alloc] init];

            NSPoint points[3];
            points[0] = NSMakePoint( rect.origin.x + (rect.size.width /2) -3, rect.size.height /2);
            points[1] = NSMakePoint( rect.origin.x + (rect.size.height /2) +3, (rect.size.height /2) +3.5);
            points[2] = NSMakePoint( rect.origin.x + (rect.size.height /2) +3, (rect.size.height /2) -3.5);

            [arrow appendBezierPathWithPoints: points count: 3];

            [[[self theme] scrollerStroke] set];
            [arrow fill];

            [path release];
            [arrow release];
        }
    }
}

- (void)drawIncrementArrow:(BOOL)highlighted {
   NSRect bounds = [self bounds];
   if ( bounds.size.width < 40 && bounds.size.height < 40 )
      return; // don't draw something stupid if too tiny to show... happens often during initial sizing 

   BOOL isHoriz = ( bounds.size.width > bounds.size.height );

    if( ! isHoriz) {

        if([arrowPosition isEqualToString: @"DoubleMax"]) {

            //Draw Increment Button
            NSRect rect = [self rectForPart: NSScrollerIncrementLine];

            if(!highlighted) {

                [[[self theme] scrollerArrowNormalGradient] drawInRect: rect angle: 0];
            } else {

                [[[self theme] scrollerArrowPushedGradient] drawInRect: rect angle: 0];
            }

            //Create Arrow Glyph
            NSBezierPath *arrow = [[NSBezierPath alloc] init];

            NSPoint points[3];
            points[0] = NSMakePoint( rect.size.width /2, rect.origin.y + (rect.size.height /2) +3);
            points[1] = NSMakePoint( (rect.size.width /2) +3.5, rect.origin.y + (rect.size.height /2) -3);
            points[2] = NSMakePoint( (rect.size.width /2) -3.5, rect.origin.y + (rect.size.height /2) -3);

            [arrow appendBezierPathWithPoints: points count: 3];

            [[[self theme] scrollerStroke] set];
            [arrow fill];

            [arrow release];
        } else {

            //Draw Decrement Button
            NSRect rect = [self rectForPart: NSScrollerIncrementLine];
            NSBezierPath *path = [[NSBezierPath alloc] init];
            NSPoint basePoints[4];

            //Add Notch
            [path appendBezierPathWithArcWithCenter: NSMakePoint((rect.size.width ) /2, (rect.origin.y  - ((rect.size.width ) /2) + 2))
                                             radius: (rect.size.width ) /2
                                         startAngle: 0
                                           endAngle: 180];

            //Add the rest of the points
            basePoints[0] = NSMakePoint( rect.origin.x, rect.origin.y);
            basePoints[1] = NSMakePoint( rect.origin.x, rect.origin.y + rect.size.height);
            basePoints[2] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
            basePoints[3] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y);

            //Add Points to Path
            [path appendBezierPathWithPoints: basePoints count: 4];

            //Fill Path
            if(!highlighted) {

                [[[self theme] scrollerArrowNormalGradient] drawInBezierPath: path angle: 0];
            } else {

                [[[self theme] scrollerArrowPushedGradient] drawInBezierPath: path angle: 0];
            }

            //Create Arrow Glyph
            NSBezierPath *arrow = [[NSBezierPath alloc] init];

            NSPoint points[3];
            points[0] = NSMakePoint( rect.size.width /2, rect.origin.y + (rect.size.height /2) +3);
            points[1] = NSMakePoint( (rect.size.width /2) +3.5, rect.origin.y + (rect.size.height /2) -3);
            points[2] = NSMakePoint( (rect.size.width /2) -3.5, rect.origin.y + (rect.size.height /2) -3);

            [arrow appendBezierPathWithPoints: points count: 3];

            [[[self theme] scrollerStroke] set];
            [arrow fill];

            [path release];
            [arrow release];
        }
    } else {

        if([arrowPosition isEqualToString: @"DoubleMax"]) {

            //Draw Increment Button
            NSRect rect = [self rectForPart: NSScrollerIncrementLine];

            if(!highlighted) {

                [[[self theme] scrollerArrowNormalGradient] drawInRect: rect angle: 90];
            } else {

                [[[self theme] scrollerArrowPushedGradient] drawInRect: rect angle: 90];
            }

            //Create Arrow Glyph
            NSBezierPath *arrow = [[NSBezierPath alloc] init];

            NSPoint points[3];
            points[0] = NSMakePoint( rect.origin.x + (rect.size.width /2) +3, rect.size.height /2);
            points[1] = NSMakePoint( rect.origin.x + (rect.size.height /2) -3, (rect.size.height /2) +3.5);
            points[2] = NSMakePoint( rect.origin.x + (rect.size.height /2) -3, (rect.size.height /2) -3.5);

            [arrow appendBezierPathWithPoints: points count: 3];

            [[[self theme] scrollerStroke] set];
            [arrow fill];

            [arrow release];
        } else {

            //Draw Decrement Button
            NSRect rect = [self rectForPart: NSScrollerIncrementLine];
            NSBezierPath *path = [[NSBezierPath alloc] init];
            NSPoint basePoints[4];

            //Add Notch
            [path appendBezierPathWithArcWithCenter: NSMakePoint(rect.origin.x - (((rect.size.height ) /2) -2), (rect.origin.y  + ((rect.size.height ) /2) ))
                                             radius: (rect.size.height ) /2
                                         startAngle: 270
                                           endAngle: 90];

            //Add the rest of the points
            basePoints[3] = NSMakePoint( rect.origin.x - (((rect.size.height ) /2) -1), rect.origin.y);
            basePoints[0] = NSMakePoint( rect.origin.x - (((rect.size.height ) /2) -1), rect.origin.y + rect.size.height);
            basePoints[1] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
            basePoints[2] = NSMakePoint( rect.origin.x + rect.size.width, rect.origin.y);

            //Add Points to Path
            [path appendBezierPathWithPoints: basePoints count: 4];

            //Fill Path
            if(!highlighted) {

                [[[self theme] scrollerArrowNormalGradient] drawInBezierPath: path angle: 0];
            } else {

                [[[self theme] scrollerArrowPushedGradient] drawInBezierPath: path angle: 0];
            }

            //Create Arrow Glyph
            NSBezierPath *arrow = [[NSBezierPath alloc] init];

            NSPoint points[3];
            points[0] = NSMakePoint( rect.origin.x + (rect.size.width /2) +3, rect.size.height /2);
            points[1] = NSMakePoint( rect.origin.x + (rect.size.height /2) -3, (rect.size.height /2) +3.5);
            points[2] = NSMakePoint( rect.origin.x + (rect.size.height /2) -3, (rect.size.height /2) -3.5);

            [arrow appendBezierPathWithPoints: points count: 3];

            [[[self theme] scrollerStroke] set];
            [arrow fill];

            [path release];
            [arrow release];
        }
    }
}
Keith Knauber
  • 752
  • 6
  • 13