You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

369 lines
11 KiB

//
// Copyright (c) 2011 Hiroshi Hashiguchi
//
// 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 "LKBadgeView.h"
#define LK_BADGE_VIEW_MINUM_WIDTH 24.0
#define LK_BADGE_VIEW_HORIZONTAL_PADDING 6.0
#define LK_BADGE_VIEW_TRUNCATED_SUFFIX @"..."
@interface LKBadgeView()
@property (nonatomic, copy) NSString* displayinText;
@property (nonatomic, assign) CGRect badgeFrame;
@end
@implementation LKBadgeView
@synthesize text = text_;
@synthesize textColor = textColor_;
@synthesize font = font_;
@synthesize badgeColor = badgeColor_;
@synthesize outlineColor;
@synthesize outlineWidth = outlineWidth_;
@synthesize outline = outline_;
@synthesize horizontalAlignment = horizontalAlignment_;
@synthesize widthMode = widthMode_;
@synthesize heightMode = heightMode_;
@synthesize displayinText;
@synthesize badgeFrame = badgeFrame_;
@synthesize shadow = shadow_;
@synthesize shadowOffset = shadowOffset_;
@synthesize shadowBlur = shadowBlur_;
@synthesize shadowColor = shadowColor_;
@synthesize shadowOfOutline = shadowOfOutline_;
@synthesize shadowOfText = shadowOfText_;
@synthesize textOffset = textOffset_;
#pragma mark - Privates
- (void)_setupBasics {
self.backgroundColor = [UIColor clearColor];
self.horizontalAlignment = LKBadgeViewHorizontalAlignmentCenter;
self.widthMode = LKBadgeViewWidthModeStandard;
self.heightMode = LKBadgeViewHeightModeStandard;
self.text = nil;
self.displayinText = nil;
self.userInteractionEnabled = NO;
self.shadowOffset = CGSizeMake(1.0, 1.0);
self.shadowBlur = 2.0;
self.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
self.textOffset = CGSizeMake(0.0, 0.0);
}
- (UIFont *)font{
if (!font_) {
font_ = [UIFont boldSystemFontOfSize:LK_BADGE_VIEW_FONT_SIZE];
}
return font_;
}
- (void)_setupDefaultWithoutOutline {
self.textColor = [UIColor whiteColor];
self.badgeColor = [UIColor grayColor];
outline_ = NO;
outlineWidth_ = 2.0;
self.outlineColor = [UIColor colorWithWhite:0.65 alpha:1.0];
[self _setupBasics];
}
- (void)_setupDefaultWithOutline {
self.textColor = [UIColor grayColor];
self.badgeColor = [UIColor whiteColor];
outline_ = YES;
outlineWidth_ = 3.0;
self.outlineColor = [UIColor colorWithWhite:0.65 alpha:1.0];
[self _setupBasics];
}
- (void)_adjustBadgeFrameX {
CGFloat realOutlineWith = outline_ ? outlineWidth_ : 0.0;
switch (self.horizontalAlignment) {
case LKBadgeViewHorizontalAlignmentLeft:
badgeFrame_.origin.x = realOutlineWith;
break;
case LKBadgeViewHorizontalAlignmentCenter:
badgeFrame_.origin.x = (self.bounds.size.width - badgeFrame_.size.width) / 2.0;
break;
case LKBadgeViewHorizontalAlignmentRight:
badgeFrame_.origin.x = self.bounds.size.width - badgeFrame_.size.width - realOutlineWith;
break;
}
}
- (void)_adjustBadgeFrameWith {
CGSize suffixSize = [LK_BADGE_VIEW_TRUNCATED_SUFFIX sizeWithAttributes:@{NSFontAttributeName: self.font}];
CGFloat paddinWidth = LK_BADGE_VIEW_HORIZONTAL_PADDING*2;
CGSize size = [self.displayinText sizeWithAttributes: @{NSFontAttributeName: self.font}];
badgeFrame_.size.width = size.width + paddinWidth;
if (badgeFrame_.size.width > self.bounds.size.width) {
while (1) {
size = [self.displayinText sizeWithAttributes: @{NSFontAttributeName: self.font}];
badgeFrame_.size.width = size.width + paddinWidth;
if (badgeFrame_.size.width+suffixSize.width > self.bounds.size.width) {
if ([self.displayinText length] > 1) {
self.displayinText = [self.displayinText substringToIndex:[self.displayinText length]-2];
} else {
self.displayinText = @" ";
break;
}
} else {
self.displayinText = [self.displayinText stringByAppendingString:LK_BADGE_VIEW_TRUNCATED_SUFFIX];
badgeFrame_.size.width += suffixSize.width;
break;
}
}
}
if (self.widthMode == LKBadgeViewWidthModeStandard) {
if (badgeFrame_.size.width < LK_BADGE_VIEw_STANDARD_WIDTH) {
badgeFrame_.size.width = LK_BADGE_VIEw_STANDARD_WIDTH;
}
}
}
- (void)_adjustBadgeFrame {
badgeFrame_.size.height = [self badgeHeight];
if (self.displayinText == nil || [self.displayinText length] == 0) {
badgeFrame_.size.width = LK_BADGE_VIEW_MINUM_WIDTH;
} else {
[self _adjustBadgeFrameWith];
}
badgeFrame_.origin.y = (self.bounds.size.height - badgeFrame_.size.height) / 2.0;
[self _adjustBadgeFrameX];
}
#pragma mark - Basics
- (id)init {
self = [super init];
if (self) {
[self _setupDefaultWithoutOutline];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self _setupDefaultWithoutOutline];
}
return self;
}
- (id)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self _setupDefaultWithoutOutline];
}
return self;
}
- (void)dealloc {
self.badgeColor = nil;
}
#pragma mark - Overrides
- (void)drawRect:(CGRect)rect {
if (self.displayinText == nil || [self.displayinText length] == 0) {
return;
}
// draw badge
UIBezierPath* outlinePath = [UIBezierPath bezierPath];
CGSize size = badgeFrame_.size;
CGFloat unit = size.height/2.0;
CGPoint bp = badgeFrame_.origin;
CGPoint c1 = CGPointMake(bp.x + unit, bp.y);
[outlinePath moveToPoint:c1];
c1.y +=unit;
[outlinePath addArcWithCenter:c1
radius:unit
startAngle:3*M_PI/2 endAngle:M_PI/2
clockwise:NO];
[outlinePath addLineToPoint:CGPointMake(bp.x + size.width - unit,
bp.y + size.height)];
CGPoint c2 = CGPointMake(bp.x + size.width - unit, bp.y + unit);
[outlinePath addArcWithCenter:c2
radius:unit
startAngle:M_PI/2 endAngle:-M_PI/2
clockwise:NO];
[outlinePath addLineToPoint:CGPointMake(bp.x + unit, bp.y)];
[self.outlineColor setStroke];
[self.badgeColor setFill];
CGContextRef context = UIGraphicsGetCurrentContext();
if (self.shadow) {
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, self.shadowOffset, self.shadowBlur, self.shadowColor.CGColor);
[outlinePath fill];
CGContextRestoreGState(context);
} else {
[outlinePath fill];
}
if (outline_) {
[outlinePath setLineWidth:outlineWidth_];
if (self.shadowOfOutline) {
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, self.shadowOffset, self.shadowBlur, self.shadowColor.CGColor);
[outlinePath stroke];
CGContextRestoreGState(context);
} else {
[outlinePath stroke];
}
}
// draw text
if (self.text != nil || [self.text length] > 0) {
[self.textColor setFill];
CGSize size = [self.displayinText sizeWithAttributes: @{NSFontAttributeName: self.font}];
CGPoint p = CGPointMake(bp.x + (badgeFrame_.size.width - size.width)/2.0 + textOffset_.width,
bp.y + (badgeFrame_.size.height - size.height)/2.0 + textOffset_.height);
if (self.shadowOfText) {
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, self.shadowOffset, self.shadowBlur, self.shadowColor.CGColor);
[self.displayinText drawAtPoint:p withAttributes: @{NSFontAttributeName: self.font}];
CGContextRestoreGState(context);
} else {
[self.displayinText drawAtPoint:p withAttributes: @{NSFontAttributeName: self.font}];
}
}
}
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
[self _adjustBadgeFrame];
}
#pragma mark - Properties
- (void)setText:(NSString *)text {
text_ = text;
self.displayinText = text;
[self _adjustBadgeFrame];
[self setNeedsDisplay];
}
- (void)setHorizontalAlignment:(LKBadgeViewHorizontalAlignment)horizontalAlignment {
horizontalAlignment_ = horizontalAlignment;
[self _adjustBadgeFrameX];
[self setNeedsDisplay];
}
- (void)setWidthMode:(LKBadgeViewWidthMode)widthMode {
widthMode_ = widthMode;
[self _adjustBadgeFrameWith];
[self setNeedsDisplay];
}
- (void)setOutlineWidth:(CGFloat)outlineWidth {
outlineWidth_ = outlineWidth;
[self _adjustBadgeFrame];
[self setNeedsDisplay];
}
- (void)setOutline:(BOOL)outline {
outline_ = outline;
[self setNeedsDisplay];
}
- (void)setShadow:(BOOL)shadow {
shadow_ = shadow;
[self setNeedsDisplay];
}
- (void)setShadowOfOutline:(BOOL)shadowOfOutline {
shadowOfOutline_ = shadowOfOutline;
[self setNeedsDisplay];
}
- (void)setShadowOfText:(BOOL)shadowOfText {
shadowOfText_ = shadowOfText;
[self setNeedsDisplay];
}
- (void)setBadgeColor:(UIColor *)badgeColor {
badgeColor_ = badgeColor;
[self setNeedsDisplay];
}
- (void)setTextColor:(UIColor *)textColor {
textColor_ = textColor;
[self setNeedsDisplay];
}
- (void)setFont:(UIFont *)font {
font_ = font;
[self _adjustBadgeFrame];
[self setNeedsDisplay];
}
#pragma mark - API (@depricated)
+ (CGFloat)badgeHeight {
return LK_BADGE_VIEW_STANDARD_HEIGHT;
}
- (CGFloat)badgeHeight {
CGFloat height;
switch (self.heightMode) {
case LKBadgeViewHeightModeStandard:
height = LK_BADGE_VIEW_STANDARD_HEIGHT;
break;
case LKBadgeViewHeightModeLarge:
height = LK_BADGE_VIEW_LARGE_HEIGHT;
break;
default:
break;
}
return height;
}
@end