Skip to content

Instantly share code, notes, and snippets.

@kosso
Last active August 15, 2016 05:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kosso/954c127fe0829a6d2ee9bc8ec6937701 to your computer and use it in GitHub Desktop.
Save kosso/954c127fe0829a6d2ee9bc8ec6937701 to your computer and use it in GitHub Desktop.
Hacked version of TiUIAttributedStringProxy.m to try to add support for ParagraphStyle and Attachment attributed strings.
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2015 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
#if defined (USE_TI_UIATTRIBUTEDSTRING) || defined(USE_TI_UIIOSATTRIBUTEDSTRING)
#import "TiUIAttributedStringProxy.h"
#import "TiProxy.h"
#import "TiUtils.h"
@implementation TiUIAttributedStringProxy
-(void)_destroy
{
RELEASE_TO_NIL(_attributedString)
RELEASE_TO_NIL(attributes)
[super _destroy];
}
-(void)_initWithProperties:(NSDictionary *)properties
{
NSString* text = [properties valueForKey:@"text"];
if(!text) {
DebugLog(@"[WARN] Ti.UI.AttributedString.text not set");
}
_attributedString = [[NSMutableAttributedString alloc] initWithString:text];
attributes = [[NSMutableArray alloc] init];
[super _initWithProperties:properties];
}
-(NSString*)apiName
{
return @"Ti.UI.AttributedString";
}
-(NSMutableAttributedString*)attributedString
{
return _attributedString;
}
-(void)addAttribute:(id)args
{
ENSURE_SINGLE_ARG(args, NSDictionary)
NSNumber *type = [args valueForKey:@"type"];
if(!type) {
DebugLog(@"[WARN] Ti.UI.AttributedString.type not set");
return;
}
id value = [args valueForKey:@"value"];
if(!value) {
DebugLog(@"[WARN] Ti.UI.AttributedString.value not set");
return;
}
NSArray *range = [args valueForKey:@"range"];
if(!range) {
DebugLog(@"[WARN] Ti.UI.AttributedString.range not set");
return;
}
if([range count] < 2) {
DebugLog(@"[WARN] Ti.UI.AttributedString.range must be an array of two numbers");
return;
}
// Kosso moved
NSInteger from = [TiUtils intValue:[range objectAtIndex:0]];
NSInteger length = [TiUtils intValue:[range objectAtIndex:1]];
NSRange rangeValue = NSMakeRange(from, length);
// Kosso added
BOOL isImage = NO;
double width = 0;
if([args valueForKey:@"width"]){
// For image attachment scaling
width = [TiUtils doubleValue:[args valueForKey:@"width"]];
NSLog(@"[INFO] requested attachment width %f", width);
}
NSString *attrName = nil;
NSString *errorMessage = nil;
id attrValue = nil;
switch ([type integerValue]) {
case AttributeNameFont:
attrName = NSFontAttributeName;
WebFont *strFont = [TiUtils fontValue:value def:[WebFont defaultFont]];
attrValue = [strFont font];
break;
case AttributeNameParagraphStyle:
attrName = NSParagraphStyleAttributeName;
// errorMessage = @"ATTRIBUTE_PARAGRAPH_STYLE not yet supported";
// Kosso added
// Build a paragraphStyle with the line spacing set to the value
NSMutableParagraphStyle *cparagraphStyle = [[NSMutableParagraphStyle alloc] init];
// Might not need these two extra ones.
// cparagraphStyle.lineHeightMultiple = [TiUtils doubleValue:value];
// cparagraphStyle.maximumLineHeight = [TiUtils doubleValue:value];
cparagraphStyle.minimumLineHeight = [TiUtils doubleValue:value];
attrValue = cparagraphStyle;
// The caret will also need adjusting. Which apparently needs a delegate of LayoutManager.
break;
case AttributeNameForegroundColor:
attrName = NSForegroundColorAttributeName;
attrValue = [[TiUtils colorValue:value] _color];
break;
case AttributeNameBackgroundColor:
attrName = NSBackgroundColorAttributeName;
attrValue = [[TiUtils colorValue:value] _color];
break;
case AttributeNameLigature:
attrName = NSLigatureAttributeName;
attrValue = [TiUtils numberFromObject:value];
break;
case AttributeNameKern:
attrName = NSKernAttributeName;
attrValue = [TiUtils numberFromObject:value];
break;
case AttributeNameStrikethroughStyle:
attrName = NSStrikethroughStyleAttributeName;
attrValue = [TiUtils numberFromObject:value];
break;
case AttributeNameUnderlineStyle:
attrName = NSUnderlineStyleAttributeName;
attrValue = [TiUtils numberFromObject:value];
break;
case AttributeNameStrokeColor:
attrName = NSStrokeColorAttributeName;
attrValue = [[TiUtils colorValue:value] _color];
break;
case AttributeNameStrokeWidth:
attrName = NSStrokeWidthAttributeName;
attrValue = [TiUtils numberFromObject:value];
break;
case AttributeNameShadow:
attrName = NSShadowAttributeName;
attrValue = [TiUtils shadowValue:value];
break;
case AttributeNameVerticalGlyphForm:
attrName = NSVerticalGlyphFormAttributeName;
attrValue = [TiUtils numberFromObject:value];
break;
case AttributeNameWritingDirection:
attrName = NSWritingDirectionAttributeName;
NSMutableArray *array = [NSMutableArray array];
[array addObject:[TiUtils numberFromObject: value]];
attrValue = array;
break;
case AttributeNameTextEffect:
attrName = NSTextEffectAttributeName;
attrValue = [TiUtils stringValue:value];
break;
case AttributeNameAttachment:
attrName = NSAttachmentAttributeName;
// Kosso attempting to add support..
/*
// Adding the attribute like this in JS. Providing a value for the image url and width for requesting any scaing.
{
type: Titanium.UI.ATTRIBUTE_ATTACHMENT,
value: 'file://' + Ti.Filesystem.resourcesDirectory+ 'test.png',
width: 40, // parseFloat(Ti.Platform.displayCaps.platformWidth - 20),
range: [5, 0]
}
// range only need start index for insertion.
*/
isImage = YES;
// NSLog(@"[INFO] attachment url %@", value);
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
// textAttachment.image = [UIImage imageNamed:@"sample_image.jpg"];
textAttachment.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:value]]];
CGFloat oldWidth = textAttachment.image.size.width;
// NSLog(@"[INFO] attachment image original width is: %f", oldWidth);
CGFloat scaleFactor = oldWidth / (CGFloat)width;
textAttachment.image = [UIImage imageWithCGImage:textAttachment.image.CGImage scale:scaleFactor orientation:UIImageOrientationUp];
NSAttributedString *attrStringWithImage = [NSAttributedString attributedStringWithAttachment:textAttachment];
//[_attributedString replaceCharactersInRange:rangeValue withAttributedString:attrStringWithImage];
[_attributedString insertAttributedString:attrStringWithImage atIndex:from];
// errorMessage = @"ATTRIBUTE_ATTACHMENT not yet supported";
// Well, not officially..
break;
case AttributeNameLink:
attrName = NSLinkAttributeName;
attrValue = [TiUtils stringValue:value];
break;
case AttributeNameBaselineOffset:
attrName = NSBaselineOffsetAttributeName;
attrValue = [TiUtils numberFromObject:value];
break;
case AttributeNameUnderlineColor:
attrName = NSUnderlineColorAttributeName;
attrValue = [[TiUtils colorValue:value] _color];
break;
case AttributeNameStrikethroughColor:
attrName = NSStrikethroughColorAttributeName;
attrValue = [[TiUtils colorValue:value] _color];
break;
case AttributeNameObliqueness:
attrName = NSObliquenessAttributeName;
attrValue = [TiUtils numberFromObject:value];
break;
case AttributeNameExpansion:
attrName = NSExpansionAttributeName;
attrValue = [TiUtils numberFromObject:value];
break;
case AttributeNameLineBreak:
attrName = NSParagraphStyleAttributeName;
NSMutableParagraphStyle *paragraphStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
NSNumber * num = [TiUtils numberFromObject:value];
[paragraphStyle setLineBreakMode:[num unsignedIntegerValue]];
attrValue = paragraphStyle;
break;
}
if(errorMessage != nil) {
DebugLog(@"[WARN] Ti.UI.%@", errorMessage);
return;
}
if(!attrValue) {
DebugLog(@"[WARN] Ti.UI.AttributedString.value is null");
return;
}
if(!attrName) {
DebugLog(@"[WARN] Ti.UI.AttributedString.type is null");
return;
}
if((from + length) > [_attributedString length]) {
DebugLog(@"[WARN] Ti.UI.AttributedString.range must me equal to or smaller than the text length");
return;
}
[attributes addObject: args];
if(!isImage){
[_attributedString addAttribute:attrName value:attrValue range:rangeValue];
}
// Images are inserted/replaced into the _attributedString during the attributes switch above.
// [_attributedString replaceCharactersInRange:NSMakeRange(6, 1) withAttributedString:attrStringWithImage];
}
-(id)attributes
{
return attributes;
}
-(void)setAttributes:(id)args
{
ENSURE_ARRAY(args)
for(NSDictionary *attr in attributes) {
NSString *name = [attr valueForKey:@"type"];
NSArray *range = [attr valueForKey:@"range"];
NSInteger from = [[range objectAtIndex:0] integerValue];
NSInteger length = [[range objectAtIndex:1] integerValue];
NSRange rangeValue = NSMakeRange(from, length);
[_attributedString removeAttribute:name range:rangeValue];
}
[attributes removeAllObjects];
for (id jsAttribute in args) {
[self addAttribute:jsAttribute];
}
}
@end
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment