Skip to content
This repository has been archived by the owner on Oct 5, 2018. It is now read-only.

Commit

Permalink
Added a AKOMultiColumnTextViewDataSource protocol, which makes it eas…
Browse files Browse the repository at this point in the history
…y to add views in the columns of the text; thanks to Christian Menschel from tapwork.de for the contribution!
  • Loading branch information
Adrian Kosmaczewski committed Jul 7, 2011
1 parent 6f1160f commit 9378ecd
Show file tree
Hide file tree
Showing 9 changed files with 353 additions and 249 deletions.
4 changes: 3 additions & 1 deletion Classes/Controllers/PageController.h
Expand Up @@ -7,11 +7,13 @@
//

#import <UIKit/UIKit.h>
#import "AKOMultiColumnTextViewDataSource.h"


@class AKOMultiPageTextView;
@class AKOCustomFontLabel;

@interface PageController : UIViewController
@interface PageController : UIViewController <AKOMultiColumnTextViewDataSource>
{
@private
AKOMultiPageTextView *_multiPageView;
Expand Down
21 changes: 18 additions & 3 deletions Classes/Controllers/PageController.m
Expand Up @@ -47,15 +47,30 @@ - (void)viewDidLoad


self.fontSize = 24.0;

self.multiPageView.dataSource = self;
self.multiPageView.columnInset = CGPointMake(50, 30);
self.multiPageView.text = [NSString stringFromFileNamed:@"lorem_ipsum.txt"];
self.multiPageView.font = [UIFont fontWithName:@"Georgia" size:self.fontSize];
self.multiPageView.columnCount = UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? 3 : 4;
self.multiPageView.columnCount = UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? 2 : 3;

UIPinchGestureRecognizer *pinchRecognizer = [[[UIPinchGestureRecognizer alloc] initWithTarget:self
action:@selector(changeTextSize:)] autorelease];
[self.multiPageView addGestureRecognizer:pinchRecognizer];
}

- (UIView*)akoMultiColumnTextView:(AKOMultiColumnTextView*)textView viewForColumn:(NSInteger)column onPage:(NSInteger)page
{
if (page == 0 && column == 1)
{
UIView *view = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 200)] autorelease];
view.backgroundColor = [UIColor redColor];
return view;
}

return nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
Expand All @@ -71,11 +86,11 @@ - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interf
{
if (UIInterfaceOrientationIsPortrait(interfaceOrientation))
{
self.multiPageView.columnCount = 3;
self.multiPageView.columnCount = 2;
}
else
{
self.multiPageView.columnCount = 4;
self.multiPageView.columnCount = 3;
}
[self.multiPageView setNeedsDisplay];
[self.label setNeedsDisplay];
Expand Down
20 changes: 20 additions & 0 deletions Classes/Helpers/AKOMultiColumnTextViewDataSource.h
@@ -0,0 +1,20 @@
//
// AKOMultiColumnTextViewDataSource.h
// CoreTextWrapper
//
// Created by Christian Menschel on 12.05.11.
// Copyright 2011 akosma software. All rights reserved.
//

#import <Foundation/Foundation.h>

@class AKOMultiColumnTextView;

@protocol AKOMultiColumnTextViewDataSource <NSObject>

@optional

- (UIView*)akoMultiColumnTextView:(AKOMultiColumnTextView*)textView viewForColumn:(NSInteger)column onPage:(NSInteger)page;


@end
24 changes: 24 additions & 0 deletions Classes/Views/AKOMultiColumnTextView.h
Expand Up @@ -8,6 +8,7 @@

#import <UIKit/UIKit.h>
#import <CoreText/CoreText.h>
#import "AKOMultiColumnTextViewDataSource.h"

@interface AKOMultiColumnTextView : UIView
{
Expand All @@ -22,6 +23,17 @@
CFIndex _startIndex;
CFIndex _finalIndex;
BOOL _moreTextAvailable;

CTLineBreakMode _lineBreakMode;
CTTextAlignment _textAlignment;
CGFloat _firstLineHeadIndent;
CGFloat _spacing;
CGFloat _topSpacing;
CGFloat _lineSpacing;
CGPoint _columnInset;

NSInteger _page;
id <AKOMultiColumnTextViewDataSource> _dataSource;
}

@property (nonatomic) NSInteger columnCount;
Expand All @@ -32,4 +44,16 @@
@property (nonatomic, readonly) CFIndex finalIndex;
@property (nonatomic, readonly) BOOL moreTextAvailable;

@property (nonatomic, assign) CTLineBreakMode lineBreakMode;
@property (nonatomic, assign) CTTextAlignment textAlignment;
@property (nonatomic, assign) CGFloat firstLineHeadIndent;
@property (nonatomic, assign) CGFloat spacing;
@property (nonatomic, assign) CGFloat topSpacing;
@property (nonatomic, assign) CGFloat lineSpacing;
@property (nonatomic, assign) CGPoint columnInset;

@property (nonatomic, assign) id <AKOMultiColumnTextViewDataSource> dataSource;

@end


136 changes: 118 additions & 18 deletions Classes/Views/AKOMultiColumnTextView.m
@@ -1,4 +1,4 @@
//

// AKOMultiColumnTextView.m
// CoreTextWrapper
//
Expand All @@ -17,7 +17,7 @@ - (void)updateAttributedString;
- (void)updateFrames;
- (void)setup;
- (void)createColumns;

- (void)setPage:(NSInteger)page;
@end


Expand All @@ -32,6 +32,16 @@ @implementation AKOMultiColumnTextView
@synthesize moreTextAvailable = _moreTextAvailable;
@synthesize attributedString = _attributedString;

@synthesize lineBreakMode = _lineBreakMode;
@synthesize textAlignment = _textAlignment;
@synthesize firstLineHeadIndent = _firstLineHeadIndent;
@synthesize spacing = _spacing;
@synthesize topSpacing = _topSpacing;
@synthesize lineSpacing = _lineSpacing;
@synthesize columnInset = _columnInset;

@synthesize dataSource = _dataSource;

#pragma mark -
#pragma mark Init and dealloc

Expand All @@ -47,11 +57,20 @@ - (void)setup
_moreTextAvailable = NO;
_columnPaths = NULL;
_frames = NULL;


_lineBreakMode = kCTLineBreakByWordWrapping;
_textAlignment = kCTLeftTextAlignment;
_firstLineHeadIndent = 0.0;
_spacing = 5.0;
_topSpacing = 3.0;
_lineSpacing = 1.0;
_columnInset = CGPointMake(10.0, 10.0);
}

- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
if ((self = [super initWithFrame:frame]))
{
[self setup];
}
Expand All @@ -60,7 +79,7 @@ - (id)initWithFrame:(CGRect)frame

- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder])
if ((self = [super initWithCoder:aDecoder]))
{
[self setup];
}
Expand All @@ -79,6 +98,7 @@ - (void)dealloc
CFRelease(_frames);
}

self.dataSource = nil;
self.attributedString = nil;

[_text release];
Expand Down Expand Up @@ -127,6 +147,19 @@ - (NSString *)text
return _text;
}

- (void)setDataSource:(id<AKOMultiColumnTextViewDataSource>)dataSource
{
if (![_dataSource isEqual:dataSource])
{
_dataSource = dataSource;
if (dataSource != nil)
{
[self updateFrames];
[self setNeedsDisplay];
}
}
}

- (void)setText:(NSString *)newText
{
if (![_text isEqualToString:newText])
Expand Down Expand Up @@ -155,6 +188,8 @@ - (void)setColumnCount:(NSInteger)newColumnCount
}
}



#pragma mark -
#pragma mark Drawing methods

Expand Down Expand Up @@ -183,6 +218,7 @@ - (void)drawRect:(CGRect)rect

- (void)createColumns
{

int column;
CGRect* columnRects = (CGRect*)calloc(_columnCount, sizeof(*columnRects));

Expand All @@ -203,7 +239,7 @@ - (void)createColumns
// Inset all columns by a few pixels of margin.
for (column = 0; column < _columnCount; column++)
{
columnRects[column] = CGRectInset(columnRects[column], 10.0, 10.0);
columnRects[column] = CGRectInset(columnRects[column], _columnInset.x, _columnInset.y);
}

// Create an array of layout paths, one for each column.
Expand All @@ -215,11 +251,75 @@ - (void)createColumns
for (column = 0; column < _columnCount; column++)
{
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, columnRects[column]);


// ask the delegate here
UIView *columnView = nil;
if ([self.dataSource respondsToSelector:@selector(akoMultiColumnTextView:viewForColumn:onPage:)])
{
columnView = [self.dataSource akoMultiColumnTextView:self viewForColumn:column onPage:_page];
}
if (columnView != nil)
{
CGRect columnRect = columnRects[column];
CGRect rectFromView = columnView.frame;
CGFloat cutLine = 0;
CGFloat drawYOffset = 0;
BOOL drawAbove = YES;


if (rectFromView.origin.y < 0)
{
cutLine = rectFromView.origin.y+rectFromView.size.height + _columnInset.y;
}
else if (rectFromView.origin.y+rectFromView.size.height >= columnRect.size.height)
{
cutLine = columnRect.size.height-(columnRect.size.height - rectFromView.origin.y) - _columnInset.y;
drawAbove = NO;
drawYOffset = columnRect.size.height-cutLine + _columnInset.y;
}
else
{
cutLine = rectFromView.size.height+_columnInset.y;
}

CGRect rectToDraw1;
CGRect rectToDraw2;
CGRectDivide(columnRect,
&rectToDraw1,
&rectToDraw2,
cutLine,
CGRectMinYEdge);



CGRect drawRect = rectToDraw1;
if (drawAbove == YES)
{
drawRect = rectToDraw2;
}

CGPathAddRect(path, NULL, CGRectMake(drawRect.origin.x,drawYOffset +_columnInset.y, drawRect.size.width, drawRect.size.height-_columnInset.y));

// Not add the desired view on the column
columnView.frame = CGRectMake(drawRect.origin.x,
columnView.frame.origin.y + _columnInset.y,
columnView.frame.size.width,
columnView.frame.size.height);

[self addSubview:columnView];
}
else
{
CGPathAddRect(path, NULL, columnRects[column]);
}

CFArrayInsertValueAtIndex(_columnPaths, column, path);
CFRelease(path);
}
free(columnRects);


}

- (void)updateAttributedString
Expand All @@ -245,21 +345,16 @@ - (void)updateAttributedString
range:range];
}


CFIndex theNumberOfSettings = 6;
CTLineBreakMode lineBreakMode = kCTLineBreakByWordWrapping;
CTTextAlignment textAlignment = kCTLeftTextAlignment;
CGFloat indent = 10.0;
CGFloat spacing = 15.0;
CGFloat topSpacing = 5.0;
CGFloat lineSpacing = 1.0;
CTParagraphStyleSetting theSettings[6] =
{
{ kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &textAlignment },
{ kCTParagraphStyleSpecifierLineBreakMode, sizeof(CTLineBreakMode), &lineBreakMode },
{ kCTParagraphStyleSpecifierFirstLineHeadIndent, sizeof(CGFloat), &indent },
{ kCTParagraphStyleSpecifierParagraphSpacing, sizeof(CGFloat), &spacing },
{ kCTParagraphStyleSpecifierParagraphSpacingBefore, sizeof(CGFloat), &topSpacing },
{ kCTParagraphStyleSpecifierLineSpacing, sizeof(CGFloat), &lineSpacing }
{ kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &_textAlignment },
{ kCTParagraphStyleSpecifierLineBreakMode, sizeof(CTLineBreakMode), &_lineBreakMode },
{ kCTParagraphStyleSpecifierFirstLineHeadIndent, sizeof(CGFloat), &_firstLineHeadIndent },
{ kCTParagraphStyleSpecifierParagraphSpacing, sizeof(CGFloat), &_spacing },
{ kCTParagraphStyleSpecifierParagraphSpacingBefore, sizeof(CGFloat), &_topSpacing },
{ kCTParagraphStyleSpecifierLineSpacing, sizeof(CGFloat), &_lineSpacing }
};

CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(theSettings, theNumberOfSettings);
Expand Down Expand Up @@ -306,4 +401,9 @@ - (void)updateFrames
}
}

- (void)setPage:(NSInteger)page
{
_page = page;
}

@end

0 comments on commit 9378ecd

Please sign in to comment.