diff --git a/.gitignore b/.gitignore index bb59993..a501395 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ *.pyc *~.nib/ build/* +# xcode 4 +xcuserdata # Textmate - if you build your xcode projects with it *.tm_build_errors diff --git a/MTLabel.xcodeproj/project.pbxproj b/MTLabel.xcodeproj/project.pbxproj index 07f9928..6fe0283 100644 --- a/MTLabel.xcodeproj/project.pbxproj +++ b/MTLabel.xcodeproj/project.pbxproj @@ -135,6 +135,9 @@ /* Begin PBXProject section */ 147737C01391B7C100BCB59A /* Project object */ = { isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; buildConfigurationList = 147737C31391B7C100BCB59A /* Build configuration list for PBXProject "MTLabel" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; diff --git a/MTLabel/MTLabel.m b/MTLabel/MTLabel.m index 39c20ea..b191ec5 100644 --- a/MTLabel/MTLabel.m +++ b/MTLabel/MTLabel.m @@ -22,13 +22,13 @@ #define DEFAULT_FONT_SIZE 12 -@interface MTLabel () +@interface MTLabel () -(void)drawTransparentBackground; @end -CGRect CTLineGetTypographicBoundsAsRect(CTLineRef line, CGPoint lineOrigin) { +CGRect CTLineGetTypographicBoundsAsARect(CTLineRef line, CGPoint lineOrigin) { CGFloat ascent = 0; CGFloat descent = 0; CGFloat leading = 0; @@ -51,7 +51,6 @@ @implementation MTLabel @synthesize _textAlignment; @synthesize delegate; @synthesize _adjustSizeToFit; - #pragma mark - Setters -(void)setNumberOfLines:(int)numberOfLines { @@ -85,6 +84,7 @@ -(void)setText:(NSString *)text { _text = nil; } + //_text = [[text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] retain]; _text = [text retain]; [self setNeedsDisplay]; @@ -156,6 +156,7 @@ -(void)setResizeToFitText:(BOOL)resizeToFitText { if (_shouldResizeToFit != resizeToFitText) { _shouldResizeToFit = resizeToFitText; + self.clipsToBounds = NO; [self setNeedsDisplay]; } @@ -226,6 +227,7 @@ - (void)setup { self._font = [UIFont systemFontOfSize:DEFAULT_FONT_SIZE]; self._lineHeight = _font.lineHeight; self._textAlignment = MTLabelTextAlignmentLeft; + self.contentMode = UIViewContentModeRedraw; [self setOpaque:NO]; } -(id)init { @@ -333,15 +335,17 @@ - (CGFloat)textOffsetForLine:(CTLineRef)line inRect:(CGRect)rect { return x; } -- (void)drawTextInRect:(CGRect)rect inContext:(CGContextRef)context { +- (void)drawTextInRect:(CGRect)rect withFont:(UIFont *)aFont lineHeight:(CGFloat)lineHeight inContext:(CGContextRef)context { if (!_text) { return; } + CGContextClearRect(context, rect); + //Create a CoreText font object with name and size from the UIKit one - CTFontRef font = CTFontCreateWithName((CFStringRef)_font.fontName , - _font.pointSize, + CTFontRef font = CTFontCreateWithName((CFStringRef)aFont.fontName , + aFont.pointSize, NULL); //Setup the attributes dictionary with font and color @@ -360,7 +364,7 @@ - (void)drawTextInRect:(CGRect)rect inContext:(CGContextRef)context { CTTypesetterRef typeSetter = CTTypesetterCreateWithAttributedString((CFAttributedStringRef)attributedString); //Start drawing from the upper side of view (the context is flipped, so we need to grab the height to do so) - CGFloat y = self.bounds.origin.y + self.bounds.size.height - _font.ascender; + CGFloat y = rect.origin.y + rect.size.height - aFont.ascender; BOOL shouldDrawAlong = YES; int count = 0; @@ -374,7 +378,7 @@ - (void)drawTextInRect:(CGRect)rect inContext:(CGContextRef)context { //Get CoreText to suggest a proper place to place the line break CFIndex lineLength = CTTypesetterSuggestLineBreak(typeSetter, currentIndex, - self.bounds.size.width); + rect.size.width); //Create a new line with from current index to line-break index CFRange lineRange = CFRangeMake(currentIndex, lineLength); @@ -383,18 +387,18 @@ - (void)drawTextInRect:(CGRect)rect inContext:(CGContextRef)context { //Create a new CTLine if we want to justify the text if (_textAlignment == MTLabelTextAlignmentJustify) { - CTLineRef justifiedLine = CTLineCreateJustifiedLine(line, 1.0, self.bounds.size.width); + CTLineRef justifiedLine = CTLineCreateJustifiedLine(line, 1.0, rect.size.width); CFRelease(line); line = nil; line = justifiedLine; } - CGFloat x = [self textOffsetForLine:line inRect:self.bounds]; + CGFloat x = [self textOffsetForLine:line inRect:rect]; // Draw highlight if color has been set if (_fontHighlightColor != nil) { CGContextSetFillColorWithColor(context, _fontHighlightColor.CGColor); - CGRect lineRect = CTLineGetTypographicBoundsAsRect(line, CGPointMake(x, y));// + (self._lineHeight - self._font.pointSize) / 2)); + CGRect lineRect = CTLineGetTypographicBoundsAsARect(line, CGPointMake(x, y));// + (self._lineHeight - self._font.pointSize) / 2)); lineRect = CGRectIntegral(lineRect); lineRect = CGRectInset(lineRect, -1, -1); @@ -423,37 +427,41 @@ - (void)drawTextInRect:(CGRect)rect inContext:(CGContextRef)context { CFRelease(line); CGFloat minFontSizeChange = 1; - y -= _lineHeight; + y -= lineHeight; currentIndex += lineLength; - _textHeight += _lineHeight; - - if (_adjustSizeToFit && _font.pointSize > _minimumFontSize) { + _textHeight += lineHeight; + + if (_adjustSizeToFit && aFont.pointSize > _minimumFontSize) { - if (self.bounds.size.height < _textHeight) { + if (rect.size.height < _textHeight) { - NSString *fontName = _font.fontName; - CGFloat pointSize = _font.pointSize; - CGFloat lineHeightRatio = self._lineHeight / pointSize; + NSString *fontName = aFont.fontName; + CGFloat pointSize = aFont.pointSize; + CGFloat lineHeightRatio = lineHeight / pointSize; CGFloat newPointSize = pointSize - minFontSizeChange; // Make sure newPointSize is not less than the _minimumFontSize newPointSize = newPointSize < _minimumFontSize ? _minimumFontSize : newPointSize; - self._font = [UIFont fontWithName:fontName size:newPointSize]; - self._lineHeight = roundf(newPointSize * lineHeightRatio); + UIFont *newFont = [UIFont fontWithName:fontName size:newPointSize]; + CGFloat newLineHeight = roundf(newPointSize * lineHeightRatio); - CGContextClearRect(context, self.bounds); + self._font = newFont; + self._lineHeight = newLineHeight; + + CGContextClearRect(context, rect); CFRelease(typeSetter); - return [self drawTextInRect:self.bounds inContext:context]; + return [self drawTextInRect:rect withFont:newFont lineHeight:newLineHeight inContext:context]; } - } + } } CFRelease(typeSetter); } + - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); @@ -464,25 +472,39 @@ - (void)drawRect:(CGRect)rect { CGContextScaleCTM(context, 1.0, -1.0); CGContextSaveGState(context); - - [self drawTextInRect:rect inContext:context]; - - if (_shouldResizeToFit && self.frame.size.height < _textHeight) { - - [self setFrame:CGRectMake(self.frame.origin.x, - self.frame.origin.y, - self.frame.size.width, - _textHeight)]; + [self drawTextInRect:rect withFont:self._font lineHeight:self._lineHeight inContext:context]; + + if (_shouldResizeToFit && rect.size.height < _textHeight) { + + + CGRect newFrame = CGRectMake(self.frame.origin.x, + self.frame.origin.y, + self.frame.size.width, + _textHeight); + [self setFrame:newFrame]; // Notify delegate that we did change frame [delegate labelDidChangeFrame:self.frame]; - // Ugly hack to avoid content being stretched - [self performSelector:@selector(setNeedsDisplay) withObject:nil afterDelay:0.0001]; + // Redraw in the new bounds + //[self setNeedsDisplayInRect:newFrame]; + //[self performSelector:@selector(setNeedsDisplay) withObject:nil afterDelay:0.000001]; + + CGRect newRect = rect; + newRect.size.height = _textHeight; + CGContextClearRect(context, newRect); + + CGContextRestoreGState(context); + //[self drawTextInRect:newRect withFont:self._font lineHeight:self._lineHeight inContext:context]; + [self performSelector:@selector(setNeedsDisplay) withObject:nil afterDelay:0.000001]; + //[self drawRect:newRect]; + + } else { + CGContextRestoreGState(context); + + [super drawRect:rect]; } - CGContextRestoreGState(context); - [super drawRect:self.bounds]; } @@ -494,7 +516,6 @@ - (void)dealloc { [_fontColor release]; _fontColor = nil; [_fontHighlightColor release], _fontHighlightColor = nil; [_font release]; _font = nil; - [super dealloc]; }