Skip to content

Commit

Permalink
* Minor improvements to the styled text system
Browse files Browse the repository at this point in the history
  • Loading branch information
joehewitt committed Apr 22, 2009
1 parent 33745b5 commit f73e8d3
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 78 deletions.
4 changes: 2 additions & 2 deletions samples/TTCatalog/Classes/StyledTextTestController.m
Expand Up @@ -77,8 +77,8 @@ - (void)loadView {
//<div class=\"inlineBox\"><div class=\"inlineBox2\">You can enclose blocks within an HTML div.</div></div>";
// NSString* kText = @"\
//<span class=\"inlineBox\"><span class=\"inlineBox2\">You can enclose blocks within an HTML div.</span></span>x";
// NSString* kText = @"\
//<div class=\"blueBox\">You can enclose blocks within an HTML div.</div>s";
// NSString* kText = @"<b>bold text</b> <span class=\"largeText\">font http://foo.com sizes</span>";
// NSString* kText = @"<a href=\"x\"><img src=\"bundle://smiley.png\"/></a> This is some text";

TTStyledTextLabel* label1 = [[[TTStyledTextLabel alloc] initWithFrame:self.view.bounds] autorelease];
label1.font = [UIFont systemFontOfSize:17];
Expand Down
5 changes: 5 additions & 0 deletions src/TTDefaultStyleSheet.m
Expand Up @@ -542,4 +542,9 @@ - (TTStyle*)toolbarButtonForState:(UIControlState)state shape:(TTShape*)shape
shadowOffset:CGSizeMake(0, -1) next:nil]]]]]]]]];
}

- (TTStyle*)selectionFillStyle:(TTStyle*)next {
return [TTLinearGradientFillStyle styleWithColor1:RGBCOLOR(5,140,245)
color2:RGBCOLOR(1,93,230) next:next];
}

@end
38 changes: 33 additions & 5 deletions src/TTStyledLayout.m
Expand Up @@ -294,7 +294,7 @@ - (void)layoutElement:(TTStyledElement*)elt {
}

UIFont* lastFont = _font;
_font = font;
self.font = font;

if (elt.firstChild) {
[self layout:elt.firstChild container:elt];
Expand All @@ -313,7 +313,7 @@ - (void)layoutElement:(TTStyledElement*)elt {
_height += padding.margin.bottom;
}
} else if (!isBlock && style) {
_inlineFrame.height += self.fontHeight;
_inlineFrame.height += _lineHeight;
if (padding) {
_x += padding.padding.right + padding.margin.right;
_lineWidth += padding.padding.right + padding.margin.right;
Expand All @@ -332,7 +332,7 @@ - (void)layoutElement:(TTStyledElement*)elt {
_inlineFrame = _inlineFrame.inlineParentFrame;
}

_font = lastFont;
self.font = lastFont;

if (style) {
[self popFrame];
Expand All @@ -341,6 +341,18 @@ - (void)layoutElement:(TTStyledElement*)elt {

- (void)layoutImage:(TTStyledImageNode*)imageNode container:(TTStyledElement*)element {
UIImage* image = [imageNode image];
CGFloat imageHeight = image.size.height;

TTStyle* style = nil;
if (imageNode.className) {
style = [[TTStyleSheet globalStyleSheet] styleWithSelector:imageNode.className];
}

TTBoxStyle* padding = style ? [style firstStyleOfClass:[TTBoxStyle class]] : nil;
if (padding) {
_x += padding.margin.left;
imageHeight += padding.margin.top + padding.margin.bottom;
}

if (_lineWidth + image.size.width > _maxWidth) {
// The image will be placed on the next line, so create a new frame for
Expand All @@ -352,8 +364,13 @@ - (void)layoutImage:(TTStyledImageNode*)imageNode container:(TTStyledElement*)el
node:imageNode] autorelease];
[self addContentFrame:frame width:image.size.width height:image.size.height];
_lineWidth += image.size.width;
if (image.size.height > _lineHeight) {
_lineHeight = image.size.height;
if (imageHeight > _lineHeight) {
_lineHeight = imageHeight;
}

if (padding) {
frame.y += padding.margin.top;
_x += padding.margin.right;
}
}

Expand Down Expand Up @@ -495,6 +512,17 @@ - (UIFont*)font {
return _font;
}

- (void)setFont:(UIFont*)font {
if (font != _font) {
[_font release];
_font = [font retain];
[_boldFont release];
_boldFont = nil;
[_italicFont release];
_italicFont = nil;
}
}

- (void)layout:(TTStyledNode*)node container:(TTStyledElement*)element {
while (node) {
if ([node isKindOfClass:[TTStyledImageNode class]]) {
Expand Down
42 changes: 41 additions & 1 deletion src/TTStyledText.m
Expand Up @@ -30,8 +30,14 @@ + (TTStyledText*)textFromXHTML:(NSString*)source lineBreaks:(BOOL)lineBreaks url
}

+ (TTStyledText*)textWithURLs:(NSString*)source {
return [self textWithURLs:source lineBreaks:NO];
}

+ (TTStyledText*)textWithURLs:(NSString*)source lineBreaks:(BOOL)lineBreaks {
TTStyledTextParser* parser = [[[TTStyledTextParser alloc] init] autorelease];
[parser parseURLs:source];
parser.parseLineBreaks = lineBreaks;
parser.parseURLs = YES;
[parser parseText:source];
if (parser.rootNode) {
return [[[TTStyledText alloc] initWithNode:parser.rootNode] autorelease];
} else {
Expand Down Expand Up @@ -138,4 +144,38 @@ - (TTStyledBoxFrame*)hitTest:(CGPoint)point {
return [self.rootFrame hitTest:point];
}

- (void)addChild:(TTStyledNode*)child {
if (!_rootNode) {
self.rootNode = child;
} else {
TTStyledNode* previousNode = _rootNode;
TTStyledNode* node = _rootNode.nextSibling;
while (node) {
previousNode = node;
node = node.nextSibling;
}
previousNode.nextSibling = child;
}
}

- (void)insertChild:(TTStyledNode*)child atIndex:(NSInteger)index {
if (!_rootNode) {
self.rootNode = child;
} else if (index == 0) {
child.nextSibling = _rootNode;
self.rootNode = child;
} else {
NSInteger i = 0;
TTStyledNode* previousNode = _rootNode;
TTStyledNode* node = _rootNode.nextSibling;
while (node && i != index) {
++i;
previousNode = node;
node = node.nextSibling;
}
child.nextSibling = node;
previousNode.nextSibling = child;
}
}

@end
140 changes: 72 additions & 68 deletions src/TTStyledTextParser.m
Expand Up @@ -43,43 +43,55 @@ - (void)popNode {

- (void)flushCharacters {
if (_chars.length) {
if (_parseLineBreaks) {
NSCharacterSet* newLines = [NSCharacterSet newlineCharacterSet];
NSInteger index = 0;
NSInteger length = _chars.length;
while (1) {
NSRange searchRange = NSMakeRange(index, length - index);
NSRange range = [_chars rangeOfCharacterFromSet:newLines options:0 range:searchRange];
if (range.location != NSNotFound) {
// Find all text before the line break and parse it
NSRange textRange = NSMakeRange(index, range.location - index);
NSString* substr = [_chars substringWithRange:textRange];
[self parseURLs:substr];

// Add a line break node after the text
TTStyledLineBreakNode* br = [[[TTStyledLineBreakNode alloc] init] autorelease];
[self addNode:br];

index = index + substr.length + 1;
} else {
// Find all text until the end of hte string and parse it
NSString* substr = [_chars substringFromIndex:index];
[self parseURLs:substr];
break;
}
}
} else if (_parseURLs) {
[self parseURLs:_chars];
} else {
TTStyledTextNode* node = [[[TTStyledTextNode alloc] initWithText:_chars] autorelease];
[self addNode:node];
}
[self parseText:_chars];
}

[_chars release];
_chars = nil;
}

- (void)parseURLs:(NSString*)string {
NSInteger index = 0;
while (index < string.length) {
NSRange searchRange = NSMakeRange(index, string.length - index);
NSRange startRange = [string rangeOfString:@"http://" options:NSCaseInsensitiveSearch
range:searchRange];
if (startRange.location == NSNotFound) {
NSString* text = [string substringWithRange:searchRange];
TTStyledTextNode* node = [[[TTStyledTextNode alloc] initWithText:text] autorelease];
[self addNode:node];
break;
} else {
NSRange beforeRange = NSMakeRange(searchRange.location,
startRange.location - searchRange.location);
if (beforeRange.length) {
NSString* text = [string substringWithRange:beforeRange];
TTStyledTextNode* node = [[[TTStyledTextNode alloc] initWithText:text] autorelease];
[self addNode:node];
}

NSRange searchRange = NSMakeRange(startRange.location, string.length - startRange.location);
NSRange endRange = [string rangeOfString:@" " options:NSCaseInsensitiveSearch
range:searchRange];
if (endRange.location == NSNotFound) {
NSString* url = [string substringWithRange:searchRange];
TTStyledLinkNode* node = [[[TTStyledLinkNode alloc] initWithText:url] autorelease];
node.url = url;
[self addNode:node];
break;
} else {
NSRange urlRange = NSMakeRange(startRange.location,
endRange.location - startRange.location);
NSString* url = [string substringWithRange:urlRange];
TTStyledLinkNode* node = [[[TTStyledLinkNode alloc] initWithText:url] autorelease];
node.url = url;
[self addNode:node];
index = endRange.location;
}
}
}
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// NSObject

Expand All @@ -91,7 +103,7 @@ - (id)init {
_chars = nil;
_stack = nil;
_parseLineBreaks = NO;
_parseURLs = YES;
_parseURLs = NO;
}
return self;
}
Expand Down Expand Up @@ -170,45 +182,37 @@ - (void)parseXHTML:(NSString*)html {
[parser parse];
}

- (void)parseURLs:(NSString*)string {
NSInteger index = 0;
while (index < string.length) {
NSRange searchRange = NSMakeRange(index, string.length - index);
NSRange startRange = [string rangeOfString:@"http://" options:NSCaseInsensitiveSearch
range:searchRange];
if (startRange.location == NSNotFound) {
NSString* text = [string substringWithRange:searchRange];
TTStyledTextNode* node = [[[TTStyledTextNode alloc] initWithText:text] autorelease];
[self addNode:node];
break;
} else {
NSRange beforeRange = NSMakeRange(searchRange.location,
startRange.location - searchRange.location);
if (beforeRange.length) {
NSString* text = [string substringWithRange:beforeRange];
TTStyledTextNode* node = [[[TTStyledTextNode alloc] initWithText:text] autorelease];
[self addNode:node];
}

NSRange searchRange = NSMakeRange(startRange.location, string.length - startRange.location);
NSRange endRange = [string rangeOfString:@" " options:NSCaseInsensitiveSearch
range:searchRange];
if (endRange.location == NSNotFound) {
NSString* url = [string substringWithRange:searchRange];
TTStyledLinkNode* node = [[[TTStyledLinkNode alloc] initWithText:url] autorelease];
node.url = url;
[self addNode:node];
break;
- (void)parseText:(NSString*)string {
if (_parseLineBreaks) {
NSCharacterSet* newLines = [NSCharacterSet newlineCharacterSet];
NSInteger index = 0;
NSInteger length = string.length;
while (1) {
NSRange searchRange = NSMakeRange(index, length - index);
NSRange range = [string rangeOfCharacterFromSet:newLines options:0 range:searchRange];
if (range.location != NSNotFound) {
// Find all text before the line break and parse it
NSRange textRange = NSMakeRange(index, range.location - index);
NSString* substr = [string substringWithRange:textRange];
[self parseURLs:substr];

// Add a line break node after the text
TTStyledLineBreakNode* br = [[[TTStyledLineBreakNode alloc] init] autorelease];
[self addNode:br];

index = index + substr.length + 1;
} else {
NSRange urlRange = NSMakeRange(startRange.location,
endRange.location - startRange.location);
NSString* url = [string substringWithRange:urlRange];
TTStyledLinkNode* node = [[[TTStyledLinkNode alloc] initWithText:url] autorelease];
node.url = url;
[self addNode:node];
index = endRange.location;
// Find all text until the end of hte string and parse it
NSString* substr = [string substringFromIndex:index];
[self parseURLs:substr];
break;
}
}
} else if (_parseURLs) {
[self parseURLs:string];
} else {
TTStyledTextNode* node = [[[TTStyledTextNode alloc] initWithText:string] autorelease];
[self addNode:node];
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/Three20/TTDefaultStyleSheet.h
Expand Up @@ -51,4 +51,6 @@
- (TTStyle*)toolbarButtonForState:(UIControlState)state shape:(TTShape*)shape
tintColor:(UIColor*)tintColor font:(UIFont*)font;

- (TTStyle*)selectionFillStyle:(TTStyle*)next;

@end
11 changes: 11 additions & 0 deletions src/Three20/TTStyledText.h
Expand Up @@ -53,6 +53,7 @@
* Only URLs are parsed, not HTML markup. URLs are turned into links.
*/
+ (TTStyledText*)textWithURLs:(NSString*)source;
+ (TTStyledText*)textWithURLs:(NSString*)source lineBreaks:(BOOL)lineBreaks;

- (id)initWithNode:(TTStyledNode*)rootNode;

Expand Down Expand Up @@ -88,4 +89,14 @@
*/
- (TTStyledBoxFrame*)hitTest:(CGPoint)point;

/**
*
*/
- (void)addChild:(TTStyledNode*)child;

/**
*
*/
- (void)insertChild:(TTStyledNode*)child atIndex:(NSInteger)index;

@end
3 changes: 1 addition & 2 deletions src/Three20/TTStyledTextParser.h
Expand Up @@ -18,7 +18,6 @@
@property(nonatomic) BOOL parseURLs;

- (void)parseXHTML:(NSString*)html;

- (void)parseURLs:(NSString*)string;
- (void)parseText:(NSString*)string;

@end
3 changes: 3 additions & 0 deletions src/Three20/Three20.h
Expand Up @@ -6,9 +6,12 @@
#import "Three20/TTDefaultStyleSheet.h"
#import "Three20/TTStyle.h"
#import "Three20/TTShape.h"

#import "Three20/TTLayout.h"

#import "Three20/TTStyledText.h"
#import "Three20/TTStyledNode.h"
#import "Three20/TTStyledTextParser.h"

#import "Three20/TTViewController.h"
#import "Three20/TTTableViewController.h"
Expand Down

0 comments on commit f73e8d3

Please sign in to comment.