diff options
Diffstat (limited to 'frontends/cocoa/BlackScroller.m')
-rw-r--r-- | frontends/cocoa/BlackScroller.m | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/frontends/cocoa/BlackScroller.m b/frontends/cocoa/BlackScroller.m new file mode 100644 index 000000000..2ee739f3a --- /dev/null +++ b/frontends/cocoa/BlackScroller.m @@ -0,0 +1,154 @@ +/* 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 |