/* Copyright 2011 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 "ArrowBox.h" @implementation ArrowBox @synthesize arrowPosition; @synthesize arrowSize; @synthesize arrowEdge; @synthesize cornerRadius; - (void) setArrowEdge: (ArrowEdge)newEdge { if (arrowEdge == newEdge) { return; } arrowEdge = newEdge; [self setNeedsDisplay: YES]; updateShadow = YES; } - (void) setArrowSize: (CGFloat)newSize { arrowSize = newSize; [self setNeedsDisplay: YES]; updateShadow = YES; } - (void) setCornerRadius: (CGFloat)newRadius { cornerRadius = newRadius; [self setNeedsDisplay: YES]; updateShadow = YES; } - (void) setArrowPosition: (CGFloat)newPosition { arrowPosition = newPosition; [self setNeedsDisplay: YES]; updateShadow = YES; } - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; if (self) { arrowPosition = 50; cornerRadius = 10; arrowSize = 15; } return self; } - (void)drawRect:(NSRect)dirtyRect { [[NSColor clearColor] set]; [NSBezierPath fillRect: dirtyRect]; NSBezierPath *path = [NSBezierPath bezierPath]; NSRect bounds = [self convertRectToBase: NSInsetRect( [self bounds], 2, 2 )]; bounds.origin.x = floor( bounds.origin.x ); bounds.origin.y = floor( bounds.origin.y ); bounds.size.width = floor( bounds.size.width ); bounds.size.height = floor( bounds.size.height ); bounds = [self convertRectFromBase: bounds]; const CGFloat right = bounds.size.width - arrowSize; const CGFloat top = bounds.size.height - arrowSize; const CGFloat left = arrowSize; const CGFloat bottom = arrowSize; [path setLineJoinStyle:NSRoundLineJoinStyle]; [path moveToPoint: NSMakePoint( right - cornerRadius, top )]; if (arrowEdge == ArrowTopEdge) { [path lineToPoint: NSMakePoint( arrowPosition + arrowSize, top )]; [path lineToPoint: NSMakePoint( arrowPosition, top + arrowSize )]; [path lineToPoint: NSMakePoint( arrowPosition - arrowSize, top )]; } [path appendBezierPathWithArcFromPoint: NSMakePoint( left, top ) toPoint: NSMakePoint( left, top - cornerRadius ) radius: cornerRadius]; if (arrowEdge == ArrowLeftEdge) { [path lineToPoint: NSMakePoint( left, bottom + arrowPosition + arrowSize )]; [path lineToPoint: NSMakePoint( left - arrowSize, bottom + arrowPosition )]; [path lineToPoint: NSMakePoint( left, bottom + arrowPosition - arrowSize )]; } [path appendBezierPathWithArcFromPoint: NSMakePoint( left, bottom ) toPoint: NSMakePoint( left + cornerRadius, bottom ) radius: cornerRadius]; if (arrowEdge == ArrowBottomEdge) { [path lineToPoint: NSMakePoint( arrowPosition - arrowSize, bottom )]; [path lineToPoint: NSMakePoint( arrowPosition, bottom - arrowSize )]; [path lineToPoint: NSMakePoint( arrowPosition + arrowSize, bottom )]; } [path appendBezierPathWithArcFromPoint: NSMakePoint( right, bottom ) toPoint: NSMakePoint( right, bottom + cornerRadius ) radius: cornerRadius]; if (arrowEdge == ArrowRightEdge) { [path lineToPoint: NSMakePoint( right, bottom + arrowPosition - arrowSize )]; [path lineToPoint: NSMakePoint( right + arrowSize, bottom + arrowPosition )]; [path lineToPoint: NSMakePoint( right, bottom + arrowPosition + arrowSize )]; } [path appendBezierPathWithArcFromPoint: NSMakePoint( right, top ) toPoint: NSMakePoint( right - cornerRadius, top ) radius: cornerRadius]; [path closePath]; [[NSColor colorWithDeviceWhite: 1.0 alpha: 0.4] set]; [[NSColor colorWithDeviceWhite: 0.0 alpha: 0.75] setFill]; NSAffineTransform *transform = [NSAffineTransform transform]; [transform translateXBy: bounds.origin.x yBy: bounds.origin.y]; [transform concat]; [path setLineWidth: 2.0]; [path fill]; [path stroke]; if (updateShadow) { [[self window] invalidateShadow]; [[self window] update]; updateShadow = NO; } } @end