Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 44 additions & 26 deletions Extras/WPHotspotLabel.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,59 +14,67 @@
@implementation WPHotspotLabel


- (instancetype)initWithCoder:(NSCoder *)coder
- (instancetype) initWithCoder:(NSCoder*)coder
{
self = [super initWithCoder:coder];
if (self) {
if (self)
{
[self addHotspotHandler];
}
return self;
}

- (instancetype)initWithFrame:(CGRect)frame
- (instancetype) initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
if (self)
{
[self addHotspotHandler];
}
return self;
}

-(void)addHotspotHandler
- (void) addHotspotHandler
{
__weak WPHotspotLabel* weakSelf = self;

[self setOnTap:^(CGPoint pt) {
// Locate the text attributes at the touched position
NSDictionary* attributes = [weakSelf textAttributesAtPoint:pt];
// If the touched attributes contains our custom action style, execute the action block
WPAttributedStyleAction* actionStyle = attributes[@"WPAttributedStyleAction"];
if (actionStyle) {
if (actionStyle)
{
actionStyle.action();
}
}];
}


-(NSDictionary*)textAttributesAtPoint:(CGPoint)pt
- (NSDictionary*) textAttributesAtPoint:(CGPoint)pt
{
// Locate the attributes of the text within the label at the specified point
NSDictionary* dictionary = nil;
CFRange currentRange = CFRangeMake(0, 0);

// First, create a CoreText framesetter
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self.attributedText);
// get the real height needed by the attributed string assuming the width of the label is fixed
CGSize size = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, currentRange, NULL, CGSizeMake(self.frame.size.width, CGFLOAT_MAX), NULL);

CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height));

CGPathAddRect(framePath, NULL, CGRectMake(0, 0, size.width, size.height));
// Get the frame that will do the rendering.
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL);
CGRect boh = CGPathGetPathBoundingBox(framePath);
CGPathRelease(framePath);

// Get each of the typeset lines
NSArray *lines = (__bridge id)CTFrameGetLines(frameRef);
NSArray* lines = (__bridge id)CTFrameGetLines(frameRef);

CFIndex linesCount = [lines count];
CGPoint *lineOrigins = (CGPoint *) malloc(sizeof(CGPoint) * linesCount);

CGPoint* lineOrigins = (CGPoint*)malloc(sizeof(CGPoint) * linesCount);
CTFrameGetLineOrigins(frameRef, CFRangeMake(0, linesCount), lineOrigins);

CTLineRef line = NULL;
Expand All @@ -75,28 +83,35 @@ -(NSDictionary*)textAttributesAtPoint:(CGPoint)pt
// Correct each of the typeset lines (which have origin (0,0)) to the correct orientation (typesetting offsets from the bottom of the frame)

CGFloat bottom = self.frame.size.height;
for(CFIndex i = 0; i < linesCount; ++i) {
lineOrigins[i].y = self.frame.size.height - lineOrigins[i].y;
bottom = lineOrigins[i].y;
CGPoint* lineOriginsReversed = (CGPoint*)malloc(sizeof(CGPoint) * linesCount);
for (CFIndex i = 0; i < linesCount; ++i)
{
lineOriginsReversed[linesCount - i -1] = lineOrigins[i];
}
free(lineOrigins);
lineOrigins = lineOriginsReversed;

// Offset the touch point by the amount of space between the top of the label frame and the text
pt.y -= (self.frame.size.height - bottom)/2;
pt.y -= (self.frame.size.height - bottom) / 2;


// Scan through each line to find the line containing the touch point y position
for(CFIndex i = 0; i < linesCount; ++i) {
for (CFIndex i = 0; i < linesCount; ++i)
{
line = (__bridge CTLineRef)[lines objectAtIndex:i];
lineOrigin = lineOrigins[i];
CGFloat descent, ascent;
CGFloat width = CTLineGetTypographicBounds(line, &ascent, &descent, nil);

if(pt.y < (floor(lineOrigin.y) + floor(descent))) {
if (pt.y < (floor(lineOrigin.y) + floor(descent)))
{
// Cater for text alignment set in the label itself (not in the attributed string)
if (self.textAlignment == NSTextAlignmentCenter) {
pt.x -= (self.frame.size.width - width)/2;
} else if (self.textAlignment == NSTextAlignmentRight) {
if (self.textAlignment == NSTextAlignmentCenter)
{
pt.x -= (self.frame.size.width - width) / 2;
}
else if (self.textAlignment == NSTextAlignmentRight)
{
pt.x -= (self.frame.size.width - width);
}

Expand All @@ -110,15 +125,18 @@ -(NSDictionary*)textAttributesAtPoint:(CGPoint)pt
// Iterate through each of the glyph runs to find the run containing the character index
NSArray* glyphRuns = (__bridge id)CTLineGetGlyphRuns(line);
CFIndex runCount = [glyphRuns count];
for (CFIndex run=0; run<runCount; run++) {
for (CFIndex run = 0; run < runCount; run++)
{
CTRunRef glyphRun = (__bridge CTRunRef)[glyphRuns objectAtIndex:run];
CFRange range = CTRunGetStringRange(glyphRun);
if (i >= range.location && i<= range.location+range.length) {
if (i >= range.location && i <= range.location + range.length)
{
dictionary = (__bridge NSDictionary*)CTRunGetAttributes(glyphRun);
break;
}
}
if (dictionary) {
if (dictionary)
{
break;
}
}
Expand Down
6 changes: 2 additions & 4 deletions WPAttributedMarkup.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@

Pod::Spec.new do |s|
s.name = "WPAttributedMarkup"
s.version = "1.0.0"
s.version = "1.0.2"
s.summary = "WPAttributedMarkup creates an attributed string from text with markup tags and a style dictionary."
s.homepage = "https://github.com/nigelgrange/WPAttributedMarkup"
# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
s.license = 'MIT'
s.author = { "Nigel Grange" => "nigel_grange@hotmail.com" }
s.source = { :git => "https://github.com/nigelgrange/WPAttributedMarkup.git", :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.source = { :git => "https://github.com/sysdatadigital/WPAttributedMarkup.git", :tag => s.version.to_s }

s.platform = :ios, '7.0'
s.requires_arc = true
Expand Down