* Remove Bindable.
Fix Observable & ObservableArray tests
Fix formattedString text
Change implementation of Span, FormattedString & TextBase
properties valueChange called before native setter

* revetred formattedString tests asserts - formattedText update text property again
properties - when getting value we now use always property name instead of key (using key could return undefined for property that is set to its default value)
updated fontSize & fontInternal properties on all controls
fix font properties so that fontInternal is reset if the new font is the same as Font.default

* fix tslint errors
This commit is contained in:
Hristo Hristov
2017-01-20 16:42:20 +02:00
committed by GitHub
parent 8382e98d80
commit e34b0f622c
32 changed files with 786 additions and 1474 deletions

View File

@ -1,13 +1,16 @@
import { TextBase as TextBaseDefinition } from "ui/text-base";
import { View, Property, CssProperty, InheritedCssProperty, Style, isIOS, Observable, makeValidator, makeParser, Length } from "ui/core/view";
import { PropertyChangeData } from "data/observable";
import { FormattedString, FormattedStringView } from "text/formatted-string";
import { addWeakEventListener, removeWeakEventListener } from "ui/core/weak-event-listener";
import { FormattedString, Span } from "text/formatted-string";
export { FormattedString };
export { FormattedString, Span };
export * from "ui/core/view";
export abstract class TextBaseCommon extends View implements TextBaseDefinition, FormattedStringView {
const CHILD_SPAN = "Span";
const CHILD_FORMATTED_TEXT = "formattedText";
const CHILD_FORMATTED_STRING = "FormattedString";
export abstract class TextBaseCommon extends View implements TextBaseDefinition {
// public abstract _setFormattedTextPropertyToNative(value: FormattedString): void;
@ -92,18 +95,25 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition,
}
public _onFormattedTextContentsChanged(data: PropertyChangeData) {
if (this._nativeView){
if (this._nativeView) {
// Notifications from the FormattedString start arriving before the Android view is even created.
this[formattedTextProperty.native] = data.value;
}
}
public _addChildFromBuilder(name: string, value: any): void {
if (!this.formattedText) {
this.formattedText = new FormattedString();
if (name === CHILD_SPAN) {
if (!this.formattedText) {
const formattedText = new FormattedString();
formattedText.spans.push(value);
this.formattedText = formattedText;
} else {
this.formattedText.spans.push(value);
}
}
else if (name === CHILD_FORMATTED_TEXT || name === CHILD_FORMATTED_STRING) {
this.formattedText = value;
}
FormattedString.addFormattedStringToView(this, name, value);
}
_requestLayoutOnTextChanged(): void {
@ -125,13 +135,13 @@ formattedTextProperty.register(TextBaseCommon);
function onFormattedTextPropertyChanged(textBase: TextBaseCommon, oldValue: FormattedString, newValue: FormattedString) {
if (oldValue) {
oldValue.parent = null;
removeWeakEventListener(oldValue, Observable.propertyChangeEvent, textBase._onFormattedTextContentsChanged, textBase);
oldValue.off(Observable.propertyChangeEvent, textBase._onFormattedTextContentsChanged, textBase);
textBase._removeView(oldValue);
}
if (newValue) {
newValue.parent = textBase;
addWeakEventListener(newValue, Observable.propertyChangeEvent, textBase._onFormattedTextContentsChanged, textBase);
textBase._addView(newValue);
newValue.on(Observable.propertyChangeEvent, textBase._onFormattedTextContentsChanged, textBase);
}
}

View File

@ -2,13 +2,15 @@
TextBaseCommon, formattedTextProperty, textAlignmentProperty, textDecorationProperty, fontSizeProperty,
textProperty, textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty,
whiteSpaceProperty, Font, Color, FormattedString, TextDecoration, TextAlignment, TextTransform, WhiteSpace,
paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length
paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length,
layout, Span
} from "./text-base-common";
import { toUIString } from "utils/types";
import { FontWeight, FontStyle } from "ui/styling/font";
export * from "./text-base-common";
export class TextBase extends TextBaseCommon {
_transformationMethod: any;
_nativeView: android.widget.TextView;
//Text
@ -26,18 +28,17 @@ export class TextBase extends TextBaseCommon {
}
set [formattedTextProperty.native](value: FormattedString) {
let spannableStringBuilder = createSpannableStringBuilder(value);
const text = (spannableStringBuilder === null || spannableStringBuilder === undefined) ? '' : <any>spannableStringBuilder;
this._nativeView.setText(text);
this._nativeView.setText(<any>spannableStringBuilder);
textProperty.nativeValueChange(this, (value === null || value === undefined) ? '' : value.toString());
if (spannableStringBuilder && this._nativeView instanceof android.widget.Button &&
!(this._nativeView.getTransformationMethod() instanceof TextTransformation)){
// Replace Android Button's default transformation (in case the developer has not already specified a text-transform) method
// with our transformation method which can handle formatted text.
// Otherwise, the default tranformation method of the Android Button will overwrite and ignore our spannableStringBuilder.
// We can't set it to NONE since it is the default value. Set it to something else first.
this.style[textTransformProperty.cssName] = TextTransform.UPPERCASE;
this.style[textTransformProperty.cssName] = TextTransform.NONE;
if (spannableStringBuilder && this._nativeView instanceof android.widget.Button &&
!(this._nativeView.getTransformationMethod() instanceof TextTransformation)) {
// Replace Android Button's default transformation (in case the developer has not already specified a text-transform) method
// with our transformation method which can handle formatted text.
// Otherwise, the default tranformation method of the Android Button will overwrite and ignore our spannableStringBuilder.
// We can't set it to NONE since it is the default value. Set it to something else first.
this.style[textTransformProperty.cssName] = TextTransform.UPPERCASE;
this.style[textTransformProperty.cssName] = TextTransform.NONE;
}
}
@ -78,24 +79,11 @@ export class TextBase extends TextBaseCommon {
}
//FontInternal
get [fontInternalProperty.native](): { typeface: android.graphics.Typeface, fontSize: number } {
let textView = this._nativeView;
return {
typeface: textView.getTypeface(),
fontSize: textView.getTextSize()
};
get [fontInternalProperty.native](): android.graphics.Typeface {
return this._nativeView.getTypeface();
}
set [fontInternalProperty.native](value: Font | { typeface: android.graphics.Typeface, fontSize: number }) {
let textView = this._nativeView;
if (value instanceof Font) {
// Set value. Note: Size is handled in fontSizeProperty.native
textView.setTypeface(value.getAndroidTypeface());
}
else {
// Reset value. Note: Resetting fontInternal will reset the size also.
textView.setTypeface(value.typeface);
textView.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.fontSize);
}
set [fontInternalProperty.native](value: Font | android.graphics.Typeface) {
this._nativeView.setTypeface(value instanceof Font ? value.getAndroidTypeface() : value);
}
//TextAlignment
@ -176,6 +164,7 @@ export class TextBase extends TextBaseCommon {
}
}
//LetterSpacing
get [letterSpacingProperty.native](): number {
return org.nativescript.widgets.ViewHelper.getLetterspacing(this._nativeView);
}
@ -224,7 +213,7 @@ class TextTransformation extends android.text.method.ReplacementTransformationMe
}
protected getOriginal(): native.Array<string> {
return convertStringToNativeCharArray(this.formattedText ? this.formattedText.toString() : this.originalText);
return convertStringToNativeCharArray(this.formattedText ? this.formattedText.toString() : this.originalText);
}
protected getReplacement(): native.Array<string> {
@ -239,7 +228,7 @@ class TextTransformation extends android.text.method.ReplacementTransformationMe
replacementString = getTransformedText(this.originalText, this.textTransform);
}
return convertStringToNativeCharArray(replacementString);
return convertStringToNativeCharArray(replacementString);
}
public getTransformation(charSeq: any, view: android.view.View): any {
@ -281,26 +270,23 @@ function getTransformedText(text: string, textTransform: TextTransform): string
function createSpannableStringBuilder(formattedString: FormattedString): android.text.SpannableStringBuilder {
let ssb = new android.text.SpannableStringBuilder();
if (formattedString === null || formattedString === undefined){
if (formattedString === null || formattedString === undefined) {
return ssb;
}
for (let i = 0, spanStart = 0, spanLength = 0, spanText = "", length = formattedString.spans.length; i < length; i++) {
let span = formattedString.spans.getItem(i);
spanText = toUIString(span.text);
if (formattedString.parent){
let textTransform = (<TextBase>formattedString.parent).textTransform;
if (textTransform){
spanText = getTransformedText(spanText, textTransform);
}
for (let i = 0, spanStart = 0, spanLength = 0, length = formattedString.spans.length; i < length; i++) {
const span = formattedString.spans.getItem(i);
const text = span.text;
const textTransform = (<TextBase>formattedString.parent).textTransform;
let spanText = (text === null || text === undefined) ? '' : text.toString();
if (textTransform) {
spanText = getTransformedText(spanText, textTransform);
}
spanLength = spanText.length;
if (spanLength !== 0) {
ssb.insert(spanStart, spanText);
span.updateSpanModifiers(formattedString);
for (let p = 0, spanModifiersLength = span.spanModifiers.length; p < spanModifiersLength; p++) {
ssb.setSpan(span.spanModifiers[p], spanStart, spanStart + spanLength, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
setSpanModifiers(ssb, span, spanStart, spanStart + spanLength);
spanStart += spanLength;
}
}
@ -315,3 +301,105 @@ function convertStringToNativeCharArray(value: string): native.Array<string> {
}
return nativeCharArray;
}
function isBold(fontWeight: FontWeight): boolean {
return fontWeight === FontWeight.BOLD
|| fontWeight === "700"
|| fontWeight === FontWeight.EXTRA_BOLD
|| fontWeight === FontWeight.BLACK;
}
function setSpanModifiers(ssb: android.text.SpannableStringBuilder, span: Span, start: number, end: number): void {
const style = span.style;
const bold = isBold(style.fontWeight);
const italic = style.fontStyle === FontStyle.ITALIC;
if (bold && italic) {
ssb.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD_ITALIC), start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
else if (bold) {
ssb.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
else if (italic) {
ssb.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.ITALIC), start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
const fontFamily = span.fontFamily;
if (fontFamily) {
const font = new Font(fontFamily, 0, (italic) ? "italic" : "normal", (bold) ? "bold" : "normal");
ensureCustomTypefaceSpanClass();
const typefaceSpan: android.text.style.TypefaceSpan = new CustomTypefaceSpanClass(fontFamily, font.getAndroidTypeface());
ssb.setSpan(typefaceSpan, start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
const realFontSize = span.fontSize;
if (realFontSize) {
ssb.setSpan(new android.text.style.AbsoluteSizeSpan(realFontSize * layout.getDisplayDensity()), start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
const color = span.color;
if (color) {
ssb.setSpan(new android.text.style.ForegroundColorSpan(color.android), start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
const backgroundColor = style.backgroundColor || (<FormattedString>span.parent).backgroundColor || (<TextBase>(<FormattedString>span.parent).parent).backgroundColor;
if (backgroundColor) {
ssb.setSpan(new android.text.style.BackgroundColorSpan(backgroundColor.android), start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
const textDecorations = style.textDecoration || (<FormattedString>span.parent).textDecoration || (<TextBase>(<FormattedString>span.parent).parent).textDecoration;
const underline = textDecorations.indexOf(TextDecoration.UNDERLINE) !== -1;
if (underline) {
ssb.setSpan(new android.text.style.UnderlineSpan(), start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
const strikethrough = textDecorations.indexOf(TextDecoration.LINE_THROUGH) !== -1;
if (strikethrough) {
ssb.setSpan(new android.text.style.StrikethroughSpan(), start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
var CustomTypefaceSpanClass;
function ensureCustomTypefaceSpanClass() {
if (CustomTypefaceSpanClass) {
return;
}
// TODO: Move this class in widgets.
class CustomTypefaceSpan extends android.text.style.TypefaceSpan {
private typeface: android.graphics.Typeface;
constructor(family: string, typeface: android.graphics.Typeface) {
super(family);
this.typeface = typeface;
return global.__native(this);
}
public updateDrawState(ds: android.text.TextPaint): void {
this.applyCustomTypeFace(ds);
}
public updateMeasureState(paint: android.text.TextPaint): void {
this.applyCustomTypeFace(paint);
}
private applyCustomTypeFace(paint: android.text.TextPaint) {
const old = paint.getTypeface();
const oldStyle = old === null ? 0 : old.getStyle();
const typeface = this.typeface;
let fake = oldStyle & ~typeface.getStyle();
if ((fake & android.graphics.Typeface.BOLD) !== 0) {
paint.setFakeBoldText(true);
}
if ((fake & android.graphics.Typeface.ITALIC) !== 0) {
paint.setTextSkewX(-0.25);
}
paint.setTypeface(typeface);
}
}
CustomTypefaceSpanClass = CustomTypefaceSpan;
}

View File

@ -1,15 +1,20 @@
import {
TextBaseCommon, textProperty, formattedTextProperty, textAlignmentProperty, textDecorationProperty,
textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty, Font, Color, FormattedString,
TextDecoration, TextAlignment, TextTransform
TextDecoration, TextAlignment, TextTransform, Span
} from "./text-base-common";
import { FontWeight, FontStyle } from "ui/styling/font";
import * as utils from "utils/utils";
import { toUIString } from "utils/types";
export * from "./text-base-common";
export class TextBase extends TextBaseCommon {
private textDecorationSet: boolean;
private textTransformSet: boolean;
private letterSpacingSet: boolean;
public nativeView: UITextField | UITextView | UILabel | UIButton;
//Text
@ -22,21 +27,17 @@ export class TextBase extends TextBaseCommon {
}
}
set [textProperty.native](value: string) {
let newValue = (value === undefined || value === null) ? '' : value.toString();
let nativeView = this.nativeView;
if (nativeView instanceof UIButton) {
const newValue = (value === undefined || value === null) ? '' : value.toString();
const nativeView = this.nativeView;
if (this.textDecorationSet || this.textTransformSet || this.letterSpacingSet) {
const style = this.style;
setTextDecorationAndTransform(newValue, nativeView, style.textDecoration, style.textTransform, style.letterSpacing, style.color);
} else if (nativeView instanceof UIButton) {
nativeView.setTitleForState(newValue, UIControlState.Normal);
//https://github.com/NativeScript/NativeScript/issues/2615
let attributedTitle = nativeView.attributedTitleForState(UIControlState.Normal);
if (attributedTitle !== null) {
let style = this.style;
setTextDecorationAndTransform(newValue, this.nativeView, style.textDecoration, style.textTransform, style.letterSpacing, style.color);
}
}
else {
} else {
nativeView.text = newValue;
}
this._requestLayoutOnTextChanged();
}
@ -45,15 +46,9 @@ export class TextBase extends TextBaseCommon {
return null;
}
set [formattedTextProperty.native](value: FormattedString) {
let mas = createNSMutableAttributedString(value);
let nativeView = this.nativeView;
if (nativeView instanceof UIButton) {
nativeView.setAttributedTitleForState(mas, UIControlState.Normal);
}
else {
nativeView.attributedText = mas;
}
textProperty.nativeValueChange(this, (value === null || value === undefined) ? '' : value.toString());
const style = this.style;
setFormattedTextDecorationAndTransform(value, this.nativeView, style.textDecoration, style.textTransform, style.letterSpacing);
textProperty.nativeValueChange(this, !value ? '' : value.toString());
}
//Color
@ -80,7 +75,7 @@ export class TextBase extends TextBaseCommon {
nativeView = nativeView instanceof UIButton ? nativeView.titleLabel : nativeView;
return nativeView.font;
}
set [fontInternalProperty.native](value: Font) {
set [fontInternalProperty.native](value: Font | UIFont) {
let nativeView = this.nativeView;
nativeView = nativeView instanceof UIButton ? nativeView.titleLabel : nativeView;
let font = value instanceof Font ? value.getUIFont(nativeView.font) : value;
@ -127,6 +122,7 @@ export class TextBase extends TextBaseCommon {
return TextDecoration.NONE;
}
set [textDecorationProperty.native](value: TextDecoration) {
this.textDecorationSet = value !== TextDecoration.NONE;
if (this.formattedText) {
setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, value, this.style.textTransform, this.style.letterSpacing);
} else {
@ -139,6 +135,7 @@ export class TextBase extends TextBaseCommon {
return TextTransform.NONE;
}
set [textTransformProperty.native](value: TextTransform) {
this.textTransformSet = value !== TextTransform.NONE;
if (this.formattedText) {
setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, this.style.textDecoration, value, this.style.letterSpacing);
} else {
@ -151,6 +148,7 @@ export class TextBase extends TextBaseCommon {
return Number.NaN;
}
set [letterSpacingProperty.native](value: number) {
this.letterSpacingSet = value !== 0;
if (this.formattedText) {
setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, this.style.textDecoration, this.style.textTransform, value);
} else {
@ -178,55 +176,18 @@ function NSStringFromNSAttributedString(source: NSAttributedString | string): NS
return NSString.stringWithString(source instanceof NSAttributedString && source.string || <string>source);
}
function updateFormattedStringTextDecoration(formattedText: FormattedString, textDecoration: TextDecoration): void {
// TODO: Refactor this method so it doesn't modify FormattedString properties.
// Instead it should create NSAttributedString and apply it to the nativeView.
switch (textDecoration) {
case TextDecoration.NONE:
formattedText.underline = NSUnderlineStyle.StyleNone;
formattedText.strikethrough = NSUnderlineStyle.StyleNone;
break;
case TextDecoration.UNDERLINE:
formattedText.underline = NSUnderlineStyle.StyleSingle;
formattedText.strikethrough = NSUnderlineStyle.StyleNone;
break;
case TextDecoration.LINE_THROUGH:
formattedText.underline = NSUnderlineStyle.StyleNone;
formattedText.strikethrough = NSUnderlineStyle.StyleSingle;
break;
case TextDecoration.UNDERLINE_LINE_THROUGH:
formattedText.underline = NSUnderlineStyle.StyleSingle;
formattedText.strikethrough = NSUnderlineStyle.StyleSingle;
break;
default:
throw new Error(`Invalid text decoration value: ${textDecoration}. Valid values are: "${TextDecoration.NONE}", "${TextDecoration.UNDERLINE}", "${TextDecoration.LINE_THROUGH}", "${TextDecoration.UNDERLINE_LINE_THROUGH}".`);
}
}
function updateFormattedStringTextTransformation(formattedText: FormattedString, textTransform: TextTransform): void {
// TODO: Refactor this method so it doesn't modify Span properties.
// Instead it should create NSAttributedString and apply it to the nativeView.
for (let i = 0, length = formattedText.spans.length; i < length; i++) {
let span = formattedText.spans.getItem(i);
span.text = getTransformedText(span.text, textTransform);
}
}
function setFormattedTextDecorationAndTransform(formattedText: FormattedString, nativeView: UITextField | UITextView | UILabel | UIButton, textDecoration: TextDecoration, textTransform: TextTransform, letterSpacing: number) {
updateFormattedStringTextDecoration(formattedText, textDecoration);
updateFormattedStringTextTransformation(formattedText, textTransform);
const attrText = createNSMutableAttributedString(formattedText);
const hasLetterSpacing = typeof letterSpacing === "number" && !isNaN(letterSpacing) && letterSpacing !== 0;
if (hasLetterSpacing) {
if (nativeView instanceof UIButton) {
let attrText = NSMutableAttributedString.alloc().initWithAttributedString(nativeView.attributedTitleForState(UIControlState.Normal));
attrText.addAttributeValueRange(NSKernAttributeName, letterSpacing * nativeView.font.pointSize, { location: 0, length: attrText.length });
nativeView.setAttributedTitleForState(attrText, UIControlState.Normal);
} else {
let attrText = NSMutableAttributedString.alloc().initWithAttributedString(nativeView.attributedText);
attrText.addAttributeValueRange(NSKernAttributeName, letterSpacing * nativeView.font.pointSize, { location: 0, length: attrText.length });
nativeView.attributedText = attrText;
}
attrText.addAttributeValueRange(NSKernAttributeName, letterSpacing * nativeView.font.pointSize, { location: 0, length: attrText.length });
}
if (nativeView instanceof UIButton) {
nativeView.setAttributedTitleForState(attrText, UIControlState.Normal);
}
else {
nativeView.attributedText = attrText;
}
}
@ -284,19 +245,91 @@ function setTextDecorationAndTransform(text: string, nativeView: UITextField | U
function createNSMutableAttributedString(formattedString: FormattedString): NSMutableAttributedString {
let mas = NSMutableAttributedString.alloc().init();
if (formattedString) {
for (let i = 0, spanStart = 0, spanLength = 0, length = formattedString.spans.length, spanText = ""; i < length; i++) {
let span = formattedString.spans.getItem(i);
spanText = toUIString(span.text);
spanLength = spanText.length;
span.updateSpanModifiers(formattedString);
let attrDict = NSMutableDictionary.alloc<string, any>().init();
for (let p = 0; p < span.spanModifiers.length; p++) {
attrDict.setObjectForKey(span.spanModifiers[p].value, span.spanModifiers[p].key);
for (let i = 0, spanStart = 0, spanLength = 0, length = formattedString.spans.length; i < length; i++) {
const span = formattedString.spans.getItem(i);
const text = span.text;
const textTransform = (<TextBase>formattedString.parent).textTransform;
let spanText = (text === null || text === undefined) ? '' : text.toString();
if (textTransform) {
spanText = getTransformedText(spanText, textTransform);
}
let nsAttributedString = NSMutableAttributedString.alloc().initWithStringAttributes(String(spanText), attrDict);
spanLength = spanText.length;
const nsAttributedString = createMutableStringForSpan(span, spanText);
mas.insertAttributedStringAtIndex(nsAttributedString, spanStart);
spanStart += spanLength;
}
}
return mas;
}
function isBold(fontWeight: FontWeight): boolean {
return fontWeight === FontWeight.BOLD
|| fontWeight === "700"
|| fontWeight === FontWeight.EXTRA_BOLD
|| fontWeight === FontWeight.BLACK;
}
function createMutableStringForSpan(span: Span, text: string): NSMutableAttributedString {
let attrDict = <{ key: string, value: any }>{};
const style = span.style;
const bold = isBold(style.fontWeight);
const italic = style.fontStyle === FontStyle.ITALIC;
let fontFamily = span.fontFamily;
let fontSize = span.fontSize;
if (bold || italic || fontFamily || fontSize) {
let font;
if (fontFamily) {
if (!fontSize) {
fontSize = utils.ios.getter(UIFont, UIFont.systemFontSize);
}
font = UIFont.fontWithNameSize(fontFamily, fontSize);
}
if (!font) {
const fontDescriptor = UIFontDescriptor.new();
let symbolicTraits;
if (bold) {
symbolicTraits |= UIFontDescriptorSymbolicTraits.TraitBold;
}
if (italic) {
symbolicTraits |= UIFontDescriptorSymbolicTraits.TraitItalic;
}
font = UIFont.fontWithDescriptorSize(fontDescriptor.fontDescriptorWithSymbolicTraits(symbolicTraits), fontSize);
}
attrDict[NSFontAttributeName] = font;
}
const color = span.color;
if (color) {
attrDict[NSForegroundColorAttributeName] = color.ios;
}
const backgroundColor = style.backgroundColor
|| (<FormattedString>span.parent).backgroundColor
|| (<TextBase>(<FormattedString>span.parent).parent).backgroundColor;
if (backgroundColor) {
attrDict[NSBackgroundColorAttributeName] = backgroundColor.ios;
}
const textDecorations = style.textDecoration
|| (<FormattedString>span.parent).textDecoration
|| (<TextBase>(<FormattedString>span.parent).parent).textDecoration;
const underline = textDecorations.indexOf(TextDecoration.UNDERLINE) !== -1;
if (underline) {
attrDict[NSUnderlineStyleAttributeName] = underline;
}
const strikethrough = textDecorations.indexOf(TextDecoration.LINE_THROUGH) !== -1;
if (strikethrough) {
attrDict[NSStrikethroughStyleAttributeName] = strikethrough;
}
return NSMutableAttributedString.alloc().initWithStringAttributes(text, <any>attrDict);
}