Created
May 3, 2013 20:07
-
-
Save alonecuzzo/5513543 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// LORichTextLabel.m | |
// RichTextLabel | |
// | |
// Created by Locassa on 19/06/2011. | |
// Copyright 2011 Locassa Ltd. All rights reserved. | |
// | |
#import "LORichTextLabel.h" | |
#import "UIView+Layout.h" | |
#import "LORichAdditionalTextLabel.h" | |
@implementation LORichTextLabel { | |
NSMutableArray *additionalHastagElements; | |
int additionalTextCounter; | |
int runningAdditionalTextCounter; | |
BOOL isBuildingLongHashtag; | |
} | |
- (id)initWithWidth:(CGFloat)aWidth { | |
self = [super initWithFrame:CGRectMake(0.0, 0.0, aWidth, 0.0)]; | |
if(self != nil) { | |
highlightStyles = [[NSMutableDictionary alloc] init]; | |
elements = [[NSMutableArray alloc] init]; | |
additionalTextCounter = 0; | |
runningAdditionalTextCounter = 1; | |
isBuildingLongHashtag = NO; | |
font = [UIFont fontWithName:@"HelveticaNeue" size:15.0]; | |
textColor = [UIColor blackColor]; | |
} | |
return self; | |
} | |
#pragma mark - | |
#pragma mark Mutators | |
- (void)addStyle:(LORichTextLabelStyle *)aStyle forPrefix:(NSString *)aPrefix { | |
if((aPrefix == nil) || (aPrefix.length == 0)) { | |
[NSException raise:NSInternalInconsistencyException | |
format:@"Prefix must be specified in %@", NSStringFromSelector(_cmd)]; | |
} | |
[highlightStyles setObject:aStyle forKey:aPrefix]; | |
} | |
- (void)setFont:(UIFont *)value { | |
if([font isEqual:value]) { | |
return; | |
} | |
font = value; | |
[self setNeedsDisplay]; | |
} | |
- (void)setTextColor:(UIColor *)value { | |
if([textColor isEqual:value]) { | |
return; | |
} | |
textColor = value; | |
[self setNeedsLayout]; | |
} | |
//- (void)addTextToAdditionalCopyArray:(NSString *)elementString pString:(NSString *)parentString { | |
// additionalTextCounter++; | |
// LORichAdditionalTextLabel *additionalTextLabel = [[LORichAdditionalTextLabel alloc] init]; | |
// additionalTextLabel.text = elementString; | |
// additionalTextLabel.parentText = parentString; | |
// additionalTextLabel.textId = additionalTextCounter; | |
// [additionalHastagElements addObject:additionalTextLabel]; | |
//} | |
//- (BOOL)stringExistsInAdditionalCopyArray:(NSString *)element { | |
// for (LORichAdditionalTextLabel *label in additionalHastagElements) { | |
// if ([label.text isEqualToString:element]) { | |
// return YES; | |
// } | |
// } | |
// return NO; | |
//} | |
-(void)fixAdditionalTextCarriageReturns:(LORichAdditionalTextLabel *)element hot:(BOOL)isHot { | |
//do what we were doing before | |
if ([element.text rangeOfString:@"\n"].location != NSNotFound) | |
{ | |
NSArray *temp = [element.text componentsSeparatedByString:@"\n"]; | |
for (NSString *tempEl in temp) | |
{ | |
if([tempEl length] == 0){ | |
LORichAdditionalTextLabel *tempAdditionalText = [[LORichAdditionalTextLabel alloc] init]; | |
tempAdditionalText.text = @"\n"; | |
tempAdditionalText.parentText = element.parentText; | |
tempAdditionalText.isHot = isHot; | |
[elements addObject:tempAdditionalText]; | |
} else { | |
LORichAdditionalTextLabel *tempAdditionalText = [[LORichAdditionalTextLabel alloc] init]; | |
tempAdditionalText.text = tempEl; | |
tempAdditionalText.parentText = element.parentText; | |
tempAdditionalText.isHot = isHot; | |
[elements addObject:tempAdditionalText]; | |
} | |
} | |
} | |
else | |
{ | |
if(element.text.length > 0){ | |
LORichAdditionalTextLabel *tempAdditionalText = [[LORichAdditionalTextLabel alloc] init]; | |
tempAdditionalText.text = element; | |
tempAdditionalText.parentText = element.parentText; | |
tempAdditionalText.isHot = isHot; | |
[elements addObject:element]; | |
} | |
} | |
} | |
//-(void)fixCarriageReturns:(NSString *)element { | |
// //do what we were doing before | |
// if ([element rangeOfString:@"\n"].location != NSNotFound) | |
// { | |
// NSArray *temp = [element componentsSeparatedByString:@"\n"]; | |
// for (NSString *tempEl in temp) | |
// { | |
// if([tempEl length] == 0){ | |
// [elements addObject:@"\n"]; | |
// } else { | |
// [elements addObject:tempEl]; | |
// } | |
// } | |
// } | |
// else | |
// { | |
// if(element.length > 0){ | |
// [elements addObject:element]; | |
// } | |
// } | |
//} | |
- (void)setText:(NSString *)value { | |
int maxStringLength = 24; | |
elements = nil; | |
elements = [NSMutableArray array]; | |
for (NSString *element in [value componentsSeparatedByString:@" "]) | |
{ | |
if ([element length] > maxStringLength) { | |
for(NSString *prefix in [highlightStyles allKeys]) { | |
//need to check and see if the element is in our fancy array | |
if([element hasPrefix:prefix]) { | |
//how many substrings is it going to have? | |
//once we find the number, pop the strings into the 'hastagarray' or something and then decrement the substring counter | |
//after each iteration | |
isBuildingLongHashtag = YES; | |
break; | |
} else { | |
isBuildingLongHashtag = NO; | |
} | |
} | |
if(!additionalHastagElements) { | |
additionalHastagElements = [[NSMutableArray alloc] init]; | |
} | |
NSMutableArray *tmpCharArray = [[NSMutableArray alloc] initWithCapacity:maxStringLength]; | |
//we're going to need to break this up so create one of the additional labels | |
for (int i = 0; i < [element length]; i++) { | |
char c = [element characterAtIndex:i]; | |
const unichar ca[] = {c}; | |
[tmpCharArray addObject:[NSString stringWithCharacters:ca length:sizeof ca / sizeof ca]]; | |
if (i > 0 && i % maxStringLength == 0) { | |
NSString *reformattedElement = [tmpCharArray componentsJoinedByString:@""]; | |
LORichAdditionalTextLabel *adText = [[LORichAdditionalTextLabel alloc] init]; | |
adText.text = reformattedElement; | |
adText.parentText = element; | |
[self fixAdditionalTextCarriageReturns:adText hot:isBuildingLongHashtag]; | |
tmpCharArray = nil; | |
tmpCharArray = [[NSMutableArray alloc] initWithCapacity:maxStringLength]; | |
} | |
} | |
if ([tmpCharArray count] > 0) { | |
LORichAdditionalTextLabel *adText = [[LORichAdditionalTextLabel alloc] init]; | |
adText.text = [tmpCharArray componentsJoinedByString:@""]; | |
adText.parentText = element; | |
[self fixAdditionalTextCarriageReturns:adText hot:isBuildingLongHashtag]; | |
} | |
tmpCharArray = nil; | |
} else { | |
LORichAdditionalTextLabel *adText = [[LORichAdditionalTextLabel alloc] init]; | |
adText.text = element; | |
adText.parentText = element; | |
[self fixAdditionalTextCarriageReturns:adText hot:NO]; | |
} | |
} | |
// NSLog(@"elements: %@", elements); | |
// NSLog(@"additional elements: %@", additionalHastagElements); | |
[self setNeedsLayout]; | |
} | |
//-(BOOL)elementShouldBeTagged:(NSString *)element { | |
// for (LORichAdditionalTextLabel *additionalElement in additionalHastagElements) { | |
// if([additionalElement.text isEqualToString:element] && runningAdditionalTextCounter == additionalElement.textId) { | |
// runningAdditionalTextCounter++; | |
// return YES; | |
// } | |
// } | |
// return NO; | |
//} | |
#pragma mark - | |
#pragma mark Drawing Methods | |
- (void)layoutSubviews { | |
[self removeSubviews]; | |
NSUInteger maxHeight = 999999; | |
CGPoint position = CGPointZero; | |
CGSize measureSize = CGSizeMake(self.size.width, maxHeight); | |
float lineHeight = -1.0f; | |
// for(NSString *element in elements) { | |
for(LORichAdditionalTextLabel *element in elements) { | |
LORichTextLabelStyle *style = nil; | |
// Find suitable style | |
for(NSString *prefix in [highlightStyles allKeys]) { | |
//need to check and see if the element is in our fancy array | |
if([element.text hasPrefix:prefix] || element.isHot == YES) { | |
style = [highlightStyles objectForKey:prefix]; | |
break; | |
} | |
} | |
UIFont *styleFont = style.font == nil ? font : style.font; | |
UIColor *styleColor = style.color == nil ? textColor : style.color; | |
// Get size of content (check current line before starting new one) | |
CGSize remainingSize = CGSizeMake(measureSize.width - position.x, maxHeight); | |
CGSize singleLineSize = CGSizeMake(remainingSize.width, 0.0); | |
CGSize controlSize = [element.text sizeWithFont:styleFont constrainedToSize:singleLineSize lineBreakMode:UILineBreakModeTailTruncation]; | |
CGSize elementSize = [element.text sizeWithFont:styleFont constrainedToSize:remainingSize]; | |
// stores the line height as measured from the element size; the line size here was never incrementing because the control size height was 0 | |
// so the lines would all overlap | |
if (lineHeight < 0 && elementSize.height > 0.0f) { | |
lineHeight = elementSize.height; | |
} | |
if(elementSize.height > controlSize.height || elementSize.width == 0) { | |
position.y += lineHeight; | |
position.x = 0.0; | |
} | |
else if (remainingSize.width <= 0) | |
{ | |
position.y += [@"LOR ftl" sizeWithFont:styleFont].height; | |
position.x = 0.0; | |
} | |
elementSize = [element.text sizeWithFont:styleFont constrainedToSize:measureSize]; | |
CGRect elementFrame = CGRectMake(position.x, position.y, elementSize.width, elementSize.height); | |
// Add button or label depending on whether we have a target | |
if(style.target != nil) { | |
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; | |
[button addTarget:style.target action:style.action forControlEvents:UIControlEventTouchUpInside]; | |
[button setTitle:element.parentText forState:UIControlStateNormal]; | |
[button setTitleColor:styleColor forState:UIControlStateNormal]; | |
[button setFrame:elementFrame]; | |
[button.titleLabel setFont:styleFont]; | |
[self addSubview:button]; | |
} else { | |
UILabel *label = [[UILabel alloc] initWithFrame:elementFrame]; | |
[label setBackgroundColor:[UIColor clearColor]]; | |
[label setNumberOfLines:maxHeight]; | |
[label setFont:styleFont]; | |
[label setTextColor:styleColor]; | |
[label setText:element.text]; | |
[self addSubview:label]; | |
} | |
CGSize spaceSize = elementSize.width == 0 ? (CGSize) {0,0} : [@" " sizeWithFont:styleFont]; | |
position.x += elementSize.width + spaceSize.width; | |
} | |
position.y += [@"this mother fucker" sizeWithFont:font].height; | |
[self setSize:CGSizeMake(self.size.width, position.y)]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment