itt 2014 - max seelemann - hello textkit!

41
Hello TextKit! Max Seelemann – The Soulmen – @macguru17

Upload: istanbul-tech-talks

Post on 13-Apr-2017

177 views

Category:

Engineering


1 download

TRANSCRIPT

Page 1: ITT 2014 - Max Seelemann - Hello TextKit!

Hello TextKit!Max Seelemann – The Soulmen – @macguru17

Page 2: ITT 2014 - Max Seelemann - Hello TextKit!
Page 3: ITT 2014 - Max Seelemann - Hello TextKit!

• General Architecture

• Syntax Highlighting

• Paragraph Numbers

Page 4: ITT 2014 - Max Seelemann - Hello TextKit!

General Architecture

Page 5: ITT 2014 - Max Seelemann - Hello TextKit!

UITextView

NSTextStorage

Text

User

Model

View

Controller

NSLayoutManageriOS 7

iOS 7

NSTextContaineriOS 7

iOS 2

Store Text

Control Layout

Define Text Area

Display + Input

Page 6: ITT 2014 - Max Seelemann - Hello TextKit!

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

Page 7: ITT 2014 - Max Seelemann - Hello TextKit!

Syntax Highlighting

Page 8: ITT 2014 - Max Seelemann - Hello TextKit!

Comments

Pragmas

Keywords

Page 9: ITT 2014 - Max Seelemann - Hello TextKit!

NSTextStorage Store Text

NSTextContainer Define Text Area

Model

NSLayoutManager Control Layout

Controller

UITextView Display + InputView

Page 10: ITT 2014 - Max Seelemann - Hello TextKit!

NSTextStorage Store Text + Attributes

Page 11: ITT 2014 - Max Seelemann - Hello TextKit!

Class Cluster

TKETextStorage

NSTextStorage Abstract

- string!- attributesAtIndex:effectiveRange:!!- replaceCharactersInRange:withString:!- setAttributes:range:

NSAttributedString

storage

Page 12: ITT 2014 - Max Seelemann - Hello TextKit!

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; }

Page 13: ITT 2014 - Max Seelemann - Hello TextKit!

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];

Page 14: ITT 2014 - Max Seelemann - Hello TextKit!
Page 15: ITT 2014 - Max Seelemann - Hello TextKit!

Code Text Storage

TKETextStorage

- string!- attributesAtIndex:effectiveRange:!!- replaceCharactersInRange:withString:!- setAttributes:range:

Text / Code

AttributesTKECodeString

storage

NSAttributedStringcache

Page 16: ITT 2014 - Max Seelemann - Hello TextKit!

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]; }

Page 17: ITT 2014 - Max Seelemann - Hello TextKit!

Text Storage Mutation

-beginEditing -endEditing

-processEditing

-replaceCharactersInRange:…

All textual changes done

-replaceCharactersInRange:…

Compute colors

Notify Change

Page 18: ITT 2014 - Max Seelemann - Hello TextKit!

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

Page 19: ITT 2014 - Max Seelemann - Hello TextKit!
Page 20: ITT 2014 - Max Seelemann - Hello TextKit!

Paragraph Numbers

Page 21: ITT 2014 - Max Seelemann - Hello TextKit!
Page 22: ITT 2014 - Max Seelemann - Hello TextKit!
Page 23: ITT 2014 - Max Seelemann - Hello TextKit!
Page 24: ITT 2014 - Max Seelemann - Hello TextKit!

NSTextContainer Define Text Area

NSTextStorage Store TextModel

NSLayoutManager Control Layout

Controller

UITextView Display + InputView

Page 25: ITT 2014 - Max Seelemann - Hello TextKit!

NSTextContainer Define Text Area

Page 26: ITT 2014 - Max Seelemann - Hello TextKit!

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

Page 27: ITT 2014 - Max Seelemann - Hello TextKit!

Line Fragment Rect- (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect

Page 28: ITT 2014 - Max Seelemann - Hello TextKit!

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; }

Page 29: ITT 2014 - Max Seelemann - Hello TextKit!

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

Page 30: ITT 2014 - Max Seelemann - Hello TextKit!

NSTextContainer

NSTextStorage

NSLayoutManager Control Layout

UITextView

Page 31: ITT 2014 - Max Seelemann - Hello TextKit!

NSTextContainer

NSTextStorage

NSLayoutManager

UITextView

Store Layout

Page 32: ITT 2014 - Max Seelemann - Hello TextKit!

NSTextContainer

NSTextStorage

NSLayoutManager

UITextView

NSGlyphGenerator

NSTypesetter

Create Layout

Store Layout

Page 33: ITT 2014 - Max Seelemann - Hello TextKit!

NSTextContainer

NSTextStorage

NSLayoutManager

UITextView

NSGlyphGenerator

NSTypesetter

Create Layout

Store Layout

NSLayoutManager Delegate

Page 34: ITT 2014 - Max Seelemann - Hello TextKit!

NSTextContainer

NSTextStorage

NSLayoutManager

UITextView

NSGlyphGenerator

NSTypesetter

Create Layout

Control Layout

NSLayoutManager Delegate

Page 35: ITT 2014 - Max Seelemann - Hello TextKit!

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

Page 36: ITT 2014 - Max Seelemann - Hello TextKit!

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

Page 37: ITT 2014 - Max Seelemann - Hello TextKit!

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]; }

Page 38: ITT 2014 - Max Seelemann - Hello TextKit!

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 ...

Page 39: ITT 2014 - Max Seelemann - Hello TextKit!
Page 40: ITT 2014 - Max Seelemann - Hello TextKit!

Demo

Page 41: ITT 2014 - Max Seelemann - Hello TextKit!

• Indented Line Wrap

• Dynamic Line Height

• Dynamic Tab Size

github.com/macguru/TextKitEditor

TextKitEditor on GitHub

Max Seelemann – @macguru17