NSScroller полупрозрачный

#macos #cocoa #nsscroller #macos-darkmode

#macos #какао #nsscroller #macos-темный режим

Вопрос:

Я использую NSScroller в приложении cocoa. NSScroller полупрозрачен в темном режиме mojave, но отлично смотрится в светлом режиме mojave.

Я попытался создать подкласс nsscroller и попытаться изменить цвет фона. он изменяет цвет фона, но эффект полупрозрачности не исчезает.

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

        NSColor.red.set()
        __NSRectFill(dirtyRect)
        self.drawKnob()
  }
}
 

Комментарии:

1. прочитайте все комментарии «draw», которые можно найти в NSScroller.h

Ответ №1:

Может быть, добавить это в свой пользовательский скроллер?

 - (BOOL) isOpaque {return YES;}
 

Почтенный BGHUDAppKit предоставляет пример того, как создавать собственные темы с нуля.
Большинство людей ненавидят это, потому что это недостижимый беспорядок.
Несмотря на это, я годами поддерживал свою собственную версию в актуальном состоянии 🙂

Вам понадобится ваша собственная реализация «темы». Например [[[self theme] scrollerStroke] set]; , необходимо вернуть NSColor . Хорошее эмпирическое правило для тем пользовательского интерфейса:

  • правило 10% Человеческий глаз может легко различить разницу в яркости в 10%, поэтому, например, полоса прокрутки должна быть выделена цветом, который на 10% ярче цвета заливки. ( контур 57.0 / 255.0, заливка 50.0 / 255.0)
  • старайтесь использовать оттенки серого как можно чаще.

Вот моя реализация с включенными примечаниями для различных версий ОС:

 //
//  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:amp;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, amp;maj);
      Gestalt(gestaltSystemVersionMinor, amp;min);
      Gestalt(gestaltSystemVersionBugFix, amp;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.2fn", rect.origin.x, rect.size.width, rect.size.height );
//      [super drawRect:[self bounds]];
//      return;
//   }

   if ( maj == 10 amp;amp; 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 amp;amp; min < 7) || ( [self usableParts] != 0 amp;amp; [self knobProportion] < 1.0 ))
   {
      // Draw knob
      [self drawKnob];
   }

   if ( maj == 10 amp;amp; 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 amp;amp; 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 amp;amp; 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 amp;amp; 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 amp;amp; 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];
        }
    }
}
 

Комментарии:

1. Привет, Кит. Может быть, вы могли бы сократить свой код до значащих битов и просто ссылаться на свою полную реализацию. Это просто слишком много кода.