diff options
Diffstat (limited to 'frontends/cocoa/ArrowBox.m')
-rw-r--r-- | frontends/cocoa/ArrowBox.m | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/frontends/cocoa/ArrowBox.m b/frontends/cocoa/ArrowBox.m new file mode 100644 index 000000000..6d6911d9b --- /dev/null +++ b/frontends/cocoa/ArrowBox.m @@ -0,0 +1,180 @@ +/* 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" + +#import "desktop/system_colour.h" +#import "cocoa/plotter.h" + +@interface ArrowBox () + +@property (nonatomic) NSColor *backgroundColor; + +@end + +@implementation ArrowBox + +@synthesize arrowPosition; +@synthesize arrowSize; +@synthesize arrowEdge; +@synthesize cornerRadius; + +- (NSColor *)backgroundColor { + if (!_backgroundColor) { + colour fill_colour; + nserror res = ns_system_colour_char("Window", &fill_colour); + NSAssert(res == NSERROR_OK, @"Expect to find the window colour"); + _backgroundColor = cocoa_convert_colour(fill_colour); + } + + return _backgroundColor; +} + +- (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.window convertRectToScreen: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.window convertRectFromScreen: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]; + [self.backgroundColor 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 |