/* Copyright (c) 1011 Sven Weidauer * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #import "BlackScroller.h" @implementation BlackScroller - (void) setFrame: (NSRect)frameRect { [super setFrame: frameRect]; if (tag != 0) [self removeTrackingRect: tag]; tag = [self addTrackingRect: [self bounds] owner: self userData: NULL assumeInside: NO]; } - (void) drawRect: (NSRect)dirtyRect { [[NSColor clearColor] set]; [NSBezierPath fillRect: dirtyRect]; if (drawTrack) [self drawKnobSlotInRect: [self rectForPart: NSScrollerKnobSlot] highlight: NO]; [self drawKnob]; } - (void) drawKnobSlotInRect: (NSRect)slotRect highlight: (BOOL)flag { slotRect = NSInsetRect( slotRect, 2, 2 ); slotRect = [self convertRectToBase: slotRect]; slotRect.origin.x = floor( slotRect.origin.x ) + 0.5; slotRect.origin.y = floor( slotRect.origin.y ) + 0.5; slotRect.size.width = floor( slotRect.size.width ); slotRect.size.height = floor( slotRect.size.height ); slotRect = [self convertRectFromBase: slotRect]; NSGradient *gradient = [[[NSGradient alloc] initWithColorsAndLocations: [NSColor clearColor], 0.0, [NSColor clearColor], 0.4, [NSColor whiteColor], 1.0, nil] autorelease]; [[NSColor whiteColor] set]; const float radius = 0.5 * ([self isHorizontal] ? NSHeight( slotRect ) : NSWidth( slotRect )); NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect: slotRect xRadius: radius yRadius: radius]; [gradient drawInBezierPath: path angle: [self isHorizontal] ? 90 : 0]; [path stroke]; } - (NSUsableScrollerParts) usableParts { return NSScrollerKnob | NSScrollerKnobSlot; } - (void) drawKnob { NSRect rect = NSInsetRect( [self rectForPart: NSScrollerKnob], 2, 2 ); rect = [self convertRectToBase: rect]; rect.origin.x = floor( rect.origin.x ) + 0.5; rect.origin.y = floor( rect.origin.y ) + 0.5; rect.size.width = floor( rect.size.width ); rect.size.height = floor( rect.size.height ); rect = [self convertRectFromBase: rect]; [[NSColor colorWithDeviceWhite: 1.0 alpha: drawTrack ? 1.0 : 0.6] set]; const float radius = 0.5 * ([self isHorizontal] ? NSHeight( rect ) : NSWidth( rect )); NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect: rect xRadius: radius yRadius: radius]; [path fill]; [path stroke]; } - (NSRect) rectForPart: (NSScrollerPart)partCode { const bool horizontal = [self isHorizontal]; NSRect rect = horizontal ? NSInsetRect( [self bounds], 4, 0 ) : NSInsetRect( [self bounds], 0, 4 ); switch (partCode) { case NSScrollerKnobSlot: return rect; case NSScrollerKnob: { const CGFloat len = horizontal ? NSWidth( rect ) : NSHeight( rect ); CGFloat knobLen = [self knobProportion] * len; const CGFloat minKnobLen = horizontal ? NSHeight( rect ) : NSWidth( rect ); if (knobLen < minKnobLen) knobLen = minKnobLen; const CGFloat start = [self doubleValue] * (len - knobLen); if (horizontal) { rect.origin.x += start; rect.size.width = knobLen; } else { rect.origin.y += start; rect.size.height = knobLen; } return rect; } default: return [super rectForPart: partCode]; } } - (BOOL) isOpaque { return NO; } - (BOOL) isHorizontal { NSRect bounds = [self bounds]; return NSWidth( bounds ) > NSHeight( bounds ); } - (void) mouseEntered: (NSEvent *)theEvent { drawTrack = YES; [self setNeedsDisplay: YES]; } - (void) mouseExited: (NSEvent *)theEvent { drawTrack = NO; [self setNeedsDisplay: YES]; } @end