itt 2014 - max seelemann - hello textkit!
TRANSCRIPT
Hello TextKit!Max Seelemann – The Soulmen – @macguru17
• General Architecture
• Syntax Highlighting
• Paragraph Numbers
General Architecture
UITextView
NSTextStorage
Text
User
Model
View
Controller
NSLayoutManageriOS 7
iOS 7
NSTextContaineriOS 7
iOS 2
Store Text
Control Layout
Define Text Area
Display + Input
UITextView
NSTextStorage
NSLayoutManager
NSTextContainer
textStorage = [NSTextStorage new]; 1
layoutManager = [NSLayoutManager new];![textStorage addLayoutManager: layoutManager]; 2
textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(…, …)];![layoutManager addTextContainer: textContainer];
3
textView = [[UITextView alloc] initWithFrame:… textContainer:textContainer]; 4
Syntax Highlighting
Comments
Pragmas
Keywords
NSTextStorage Store Text
NSTextContainer Define Text Area
Model
NSLayoutManager Control Layout
Controller
UITextView Display + InputView
NSTextStorage Store Text + Attributes
Class Cluster
TKETextStorage
NSTextStorage Abstract
- string!- attributesAtIndex:effectiveRange:!!- replaceCharactersInRange:withString:!- setAttributes:range:
NSAttributedString
storage
Simple Text Storage
TKETextStorage
NSAttributedString
storage
- (NSString *)string { return [storage string]; }
- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range { return [storage attributesAtIndex:location effectiveRange:range]; }
- (id)init { self = [super init]; ! if (self) { storage = [NSMutableAttributedString new]; } return self; }
Simple Text Storage
- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range { [storage setAttributes:attrs range:range]; ! }
- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str { [storage replaceCharactersInRange:range withString:str]; !!!}
[self edited:NSTextStorageEditedCharacters range:range changeInLength:(NSInteger)str.length - (NSInteger)range.length];
[self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
Code Text Storage
TKETextStorage
- string!- attributesAtIndex:effectiveRange:!!- replaceCharactersInRange:withString:!- setAttributes:range:
Text / Code
AttributesTKECodeString
storage
NSAttributedStringcache
Code Text Storage
- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range { [cache setAttributes:attrs range:range]; ! [self edited:NSTextStorageEditedAttributes range:range changeInLength:0]; }
- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str { [storage replaceCharactersInRange:range withString:str]; [cache replaceCharactersInRange:range withString:str]; ! [self edited:NSTextStorageEditedCharacters range:range changeInLength:(NSInteger)str.length - (NSInteger)range.length]; }
Text Storage Mutation
-beginEditing -endEditing
-processEditing
-replaceCharactersInRange:…
All textual changes done
-replaceCharactersInRange:…
Compute colors
Notify Change
Compute Colors
- (void)processEditing { ... // Clean up colors !! [self.content enumerateCodeInRange:range usingBlock:^(NSRange range, TKECodeType type) { ! [self addAttribute:NSForegroundColorAttributeName value:[self textColorForCodeType: type] range:range]; ! }]; ! [super processEditing]; }
CodeString knows code
TextStorage maps colors
Paragraph Numbers
NSTextContainer Define Text Area
NSTextStorage Store TextModel
NSLayoutManager Control Layout
Controller
UITextView Display + InputView
NSTextContainer Define Text Area
NSTextContainer
Vivamus et turpis in dui blandit pulvinar nec dignissim diam. Nulla scelerisque posuere viverra. Quisque nibh nunc, consequat vel luctus in, consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum enim. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus hendrerit venenatis libero, vitae sodales lacus elementum eget. Duis sit amet risus ac nunc blandit lobortis vel sed nibh. Suspendisse laoreet odio ac ligula aliquam scelerisque. Nulla volutpat consectetur sem tincidunt cursus. In ac justo in libero. Fusce tincidunt erat sit amet magna porttitor nec iaculis diam varius. Aliquam eget odio leo. Sed faucibus, libero non consectetur tristique, metus leo tempus libero, quis ornare felis purus in odio. Proin metus arcu, dictum id faucibus gravida, pulvinar ut metus. Mauris nisl sapien, cursus nec auctor quis, bibendum vitae. Etiam id nisl libero, nec consequat dolor. Fusce id ornare enim. Praesent viverra rutrum erat, eu gravida erat scelerisque at. Donec sed lectus leo. Nunc vel volutpat libero. Maecenas euismod molestie neque non feugiat. Vestibulum hendrerit lorem leo, condimentum imperdiet velit. Quisque urna nisi, faucibus id
Vivamus et turpis in dui blandit pulvinar nec dignissim diam. Nulla scelerisque posuere viverra. Quisque nibh nunc, consequat vel luctus in, consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum enim. Cum sociis natoque penatibus et magnis dis p a r t u r i e n t montes , nascetur r i d i c u l u s m u s . P h a s e l l u s hendrer i t venenatis libero, v i t a e s o d a l e s l a c u s elementum eget. Du is s i t amet risus ac nunc b l a n d i t lobortis vel sed nibh. Suspendisse laoreet o d i o a c ligula aliquam scelerisque. Nul la volutpat consectetur sem tincidunt cursus. In ac justo in libero. Fusce tincidunt erat sit amet magna porttitor nec iaculis diam varius. Aliquam eget odio leo. Sed faucibus, libero non consectetur tristique, metus leo tempus libero, quis ornare felis purus in odio. Proin metus arcu, dictum id faucibus gravida, pulvinar ut metus. Mauris nisl sapien, cursus nec auctor quis, bibendum vitae. Etiam id nisl libero, nec consequat dolor. Fusce id ornare enim. Praesent viverra rutrum erat, eu gravida erat scelerisque at. Donec sed
Vivamus et turpis in dui blandit pulvinar nec dignissim diam. Nulla scelerisque posuere viverra. Quisque nibh nunc, c o n s e q u a t v e l l u c t u s i n , consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. S u s p e n d i s s e p o t e n t i . Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum enim. C u m s o c i i s n a t o q u e penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus hendrerit venenatis libero, v i t a e s o d a l e s l a c u s elementum eget. Duis sit amet risus ac nunc blandit l o b o r t i s v e l s e d n i b h . Suspendisse laoreet odio ac ligula aliquam scelerisque.
Nulla volutpat consectetur sem tincidunt cursus. In ac justo in
libero. Fusce tincidunt erat sit amet magna porttitor nec iaculis diam varius.
Aliquam eget odio leo. Sed faucibus,
V i v a m u s et turpis in dui blandit
pulvinar nec dignissim diam. Nul la sce ler isque posuere
v i v e r r a . Q u i s q u e n i b h n u n c , consequat vel luctus in, consectetur
vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec.
Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum enim. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus hendrerit venenatis libero, vitae sodales lacus elementum eget. Duis sit amet risus ac nunc blandit lobortis vel sed nibh. Suspendisse laoreet odio ac ligula aliquam scelerisque. Nulla volutpat consectetur sem tincidunt cursus. In ac justo in libero. Fusce tincidunt erat sit amet magna porttitor nec iaculis diam varius. Aliquam eget odio leo. Sed faucibus, libero non consectetur tristique,
metus leo tempus libero, quis ornare felis purus in odio. Proin metus arcu, dictum
id faucibus gravida, pulvinar ut metus. Mauris nisl sapien,
cursus nec auctor quis, bibendum vitae.
Define Text Area
Line Fragment Rect- (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect
Insetting Text Container
- (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect { CGRect rect = [super lineFragmentRectForProposedRect:proposedRect atIndex:characterIndex writingDirection:baseWritingDirection remainingRect:remainingRect]; ! rect.origin.x += inset; rect.size.width -= inset; ! return rect; }
Insetting Text Container
- (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect { CGRect rect = [super lineFragmentRectForProposedRect:proposedRect atIndex:characterIndex writingDirection:baseWritingDirection remainingRect:remainingRect]; ! rect.origin.x += inset; rect.size.width -= inset; ! return rect; }
Hangs the text layout
NSTextContainer
NSTextStorage
NSLayoutManager Control Layout
UITextView
NSTextContainer
NSTextStorage
NSLayoutManager
UITextView
Store Layout
NSTextContainer
NSTextStorage
NSLayoutManager
UITextView
NSGlyphGenerator
NSTypesetter
Create Layout
Store Layout
NSTextContainer
NSTextStorage
NSLayoutManager
UITextView
NSGlyphGenerator
NSTypesetter
Create Layout
Store Layout
NSLayoutManager Delegate
NSTextContainer
NSTextStorage
NSLayoutManager
UITextView
NSGlyphGenerator
NSTypesetter
Create Layout
Control Layout
NSLayoutManager Delegate
TypesettingView
(UITextContainer)Text
(NSTextStorage)
(NSTypesetter)
Vivamus et turpis in dui b land i t pu lv ina r nec dignissim diam. Nulla s c e l e r i s q u e p o s u e re viverra. Quisque nibh nunc, consequat ve l luctus in, consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere
Line Fragment
RectCharacters to GlyphsA → AText
Attributes
Store Layout (NSLayoutManager)
Test in Istanbul
TypesettingView
(UITextContainer)Text
(NSTextStorage)
(NSTypesetter)
Vivamus et turpis in dui b land i t pu lv ina r nec dignissim diam. Nulla s c e l e r i s q u e p o s u e re viverra. Quisque nibh nunc, consequat ve l luctus in, consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere
Line Fragment
RectCharacters to GlyphsA → AText
Attributes
Store Layout (NSLayoutManager)
Test in IstanbulShorten Line
Offset Line
Offsetting Line Fragment
- (void)setLineFragmentRect:(CGRect)fragmentRect forGlyphRange:(NSRange)glyphRange usedRect:(CGRect)usedRect { fragmentRect.origin.x += inset; usedRect.origin.x += inset; [super setLineFragmentRect:fragmentRect forGlyphRange:glyphRange usedRect:usedRect]; }
Paragraph numbers- (void)drawBackgroundForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin { [super drawBackgroundForGlyphRange:glyphsToShow atPoint:origin]; !!!!!!!!!!!!!!!}
// Enumerate all lines NSUInteger glyphIndex = glyphRange.location; while (glyphIndex < NSMaxRange(glyphRange)) { !!!!!!!! // Advance glyphIndex = NSMaxRange(glyphLineRange); }
NSRange glyphLineRange; CGRect lineRect = [self lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRange:&glyphLineRange]; ! // Drawing ...
Demo
• Indented Line Wrap
• Dynamic Line Height
• Dynamic Tab Size
github.com/macguru/TextKitEditor
TextKitEditor on GitHub
Max Seelemann – @macguru17