mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
Fixed text decoration tests, Color will now store just a single argb info in 32bit unsigned int internally and covert to a/r/g/b or hex when necessary
This commit is contained in:
committed by
Panayot Cankov
parent
ccde2a4083
commit
b2cf286948
@@ -6,11 +6,6 @@ const SHARP = "#";
|
||||
const HEX_REGEX = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)|(^#[0-9A-F]{8}$)/i;
|
||||
|
||||
export class Color implements definition.Color {
|
||||
private _a: number;
|
||||
private _r: number;
|
||||
private _g: number;
|
||||
private _b: number;
|
||||
private _hex: string;
|
||||
private _argb: number;
|
||||
private _name: string;
|
||||
|
||||
@@ -25,61 +20,48 @@ export class Color implements definition.Color {
|
||||
this._argb = argbFromRgbOrRgba(arg);
|
||||
} else if (knownColors.isKnownName(arg)) {
|
||||
// The parameter is a known color name
|
||||
this._hex = knownColors.getKnownColor(arg);
|
||||
const hex = knownColors.getKnownColor(arg);
|
||||
this._name = arg;
|
||||
this._argb = this._argbFromString(this._hex);
|
||||
this._argb = this._argbFromString(hex);
|
||||
} else if (HEX_REGEX.test(arg)) {
|
||||
// The parameter is a "#AARRGGBB" formatted string
|
||||
this._hex = this._normalizeHex(arg);
|
||||
this._argb = this._argbFromString(this._hex);
|
||||
const hex = this._normalizeHex(arg);
|
||||
this._argb = this._argbFromString(hex);
|
||||
} else {
|
||||
throw new Error("Invalid color: " + arg);
|
||||
}
|
||||
} else if (types.isNumber(arg)) {
|
||||
// The parameter is a 32-bit unsigned integer where each 8 bits specify a color component
|
||||
this._argb = arg;
|
||||
// In case a 32-bit signed int (Android, Java has no unsigned types) was provided - convert to unsigned by applyint >>> 0
|
||||
this._argb = arg >>> 0;
|
||||
} else {
|
||||
throw new Error("Expected 1 or 4 constructor parameters.");
|
||||
}
|
||||
this._parseComponents();
|
||||
if (!this._hex) {
|
||||
this._hex = this._buildHex();
|
||||
}
|
||||
} else if (arguments.length === 4) {
|
||||
// TODO: Alpha may be optional
|
||||
this._a = arguments[0];
|
||||
this._r = arguments[1];
|
||||
this._g = arguments[2];
|
||||
this._b = arguments[3];
|
||||
this._buildArgb();
|
||||
this._hex = this._buildHex();
|
||||
this._argb = (arguments[0] & 0xFF) * 0x01000000
|
||||
+ (arguments[1] & 0xFF) * 0x00010000
|
||||
+ (arguments[2] & 0xFF) * 0x00000100
|
||||
+ (arguments[3] & 0xFF) * 0x00000001;
|
||||
} else {
|
||||
throw new Error("Expected 1 or 4 constructor parameters.");
|
||||
}
|
||||
}
|
||||
|
||||
get a(): number {
|
||||
return this._a;
|
||||
}
|
||||
|
||||
get r(): number {
|
||||
return this._r;
|
||||
}
|
||||
|
||||
get g(): number {
|
||||
return this._g;
|
||||
}
|
||||
|
||||
get b(): number {
|
||||
return this._b;
|
||||
}
|
||||
get a(): number { return (this._argb / 0x01000000) & 0xFF; }
|
||||
get r(): number { return (this._argb / 0x00010000) & 0xFF; }
|
||||
get g(): number { return (this._argb / 0x00000100) & 0xFF; }
|
||||
get b(): number { return (this._argb / 0x00000001) & 0xFF; }
|
||||
|
||||
get argb(): number {
|
||||
return this._argb;
|
||||
}
|
||||
|
||||
get hex(): string {
|
||||
return this._hex;
|
||||
if (this.a === 0xFF) {
|
||||
return ("#" + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b)).toUpperCase();
|
||||
} else {
|
||||
return ("#" + this._componentToHex(this.a) + this._componentToHex(this.r) + this._componentToHex(this.g) + this._componentToHex(this.b)).toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
@@ -95,7 +77,23 @@ export class Color implements definition.Color {
|
||||
}
|
||||
|
||||
public _argbFromString(hex: string): number {
|
||||
return undefined;
|
||||
if (hex.charAt(0) === "#") {
|
||||
hex = hex.substr(1);
|
||||
}
|
||||
|
||||
if (hex.length === 3) {
|
||||
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
||||
} else if (hex.length === 4) {
|
||||
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
|
||||
}
|
||||
|
||||
var intVal = parseInt(hex, 16);
|
||||
if (hex.length === 6) {
|
||||
// add the alpha component since the provided string is RRGGBB
|
||||
intVal = (intVal & 0x00FFFFFF) + 0xFF000000;
|
||||
}
|
||||
|
||||
return intVal;
|
||||
}
|
||||
|
||||
public equals(value: definition.Color): boolean {
|
||||
@@ -132,10 +130,6 @@ export class Color implements definition.Color {
|
||||
return HEX_REGEX.test(value) || isRgbOrRgba(value);
|
||||
}
|
||||
|
||||
private _buildHex(): string {
|
||||
return SHARP + this._componentToHex(this._a) + this._componentToHex(this._r) + this._componentToHex(this._g) + this._componentToHex(this._b);
|
||||
}
|
||||
|
||||
private _componentToHex(component: number): string {
|
||||
let hex = component.toString(16);
|
||||
if (hex.length === 1) {
|
||||
@@ -145,23 +139,6 @@ export class Color implements definition.Color {
|
||||
return hex;
|
||||
}
|
||||
|
||||
private _parseComponents() {
|
||||
if (types.isUndefined(this._argb)) {
|
||||
throw new Error("Missing the ARGB numeric value");
|
||||
}
|
||||
|
||||
// Format is ARGB, so alpha takes the first 8 bits, red the next, green the next and the last 8 bits are for the blue component
|
||||
this._a = (this._argb >> 24) & 255;
|
||||
this._r = (this._argb >> 16) & 255;
|
||||
this._g = (this._argb >> 8) & 255;
|
||||
this._b = this._argb & 255;
|
||||
}
|
||||
|
||||
private _buildArgb() {
|
||||
// Format is ARGB, so alpha takes the first 8 bits, red the next, green the next and the last 8 bits are for the blue component
|
||||
this._argb = (this._a << 24) | (this._r << 16) | (this._g << 8) | this._b;
|
||||
}
|
||||
|
||||
private _normalizeHex(hexStr: string): string {
|
||||
if (hexStr.charAt(0) === SHARP && hexStr.length === 4) {
|
||||
// Duplicate each char after the #, so "#123" becomes "#112233"
|
||||
@@ -208,6 +185,8 @@ function argbFromRgbOrRgba(value: string): number {
|
||||
a = Math.round(parseFloat(parts[3].trim()) * 255);
|
||||
}
|
||||
|
||||
// Format is ARGB, so alpha takes the first 8 bits, red the next, green the next and the last 8 bits are for the blue component
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
return (a & 0xFF) * 0x01000000
|
||||
+ (r & 0xFF) * 0x00010000
|
||||
+ (g & 0xFF) * 0x00000100
|
||||
+ (b & 0xFF) * 0x00000001;
|
||||
}
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
export class Color extends common.Color {
|
||||
get android(): number {
|
||||
return this.argb;
|
||||
}
|
||||
|
||||
public _argbFromString(hex: string): number {
|
||||
return android.graphics.Color.parseColor(hex);
|
||||
return this.argb >> 0;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import * as common from "./color-common";
|
||||
|
||||
var AMP = "#";
|
||||
|
||||
export class Color extends common.Color {
|
||||
private _ios: UIColor;
|
||||
|
||||
@@ -12,18 +10,4 @@ export class Color extends common.Color {
|
||||
}
|
||||
return this._ios;
|
||||
}
|
||||
|
||||
public _argbFromString(hex: string): number {
|
||||
if (hex.charAt(0) === AMP) {
|
||||
hex = hex.substr(1);
|
||||
}
|
||||
|
||||
var intVal = parseInt(hex, 16);
|
||||
if (hex.length === 6) {
|
||||
// add the alpha component since the provided string is RRGGBB
|
||||
intVal |= 255 << 24;
|
||||
}
|
||||
|
||||
return intVal;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
import { _isSet as isSet } from "ui/core/properties";
|
||||
import { FontWeight, FontStyle } from "ui/styling/font";
|
||||
import * as utils from "utils/utils";
|
||||
|
||||
export * from "./text-base-common";
|
||||
|
||||
@@ -23,11 +22,15 @@ export class TextBase extends TextBaseCommon {
|
||||
return '';
|
||||
}
|
||||
set [textProperty.native](value: string) {
|
||||
if (this.formattedText) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
this.setTextDecorationAndTransform(newValue, nativeView, style.textDecoration, style.textTransform, style.letterSpacing, style.color);
|
||||
} else if (nativeView instanceof UIButton) {
|
||||
nativeView.setTitleForState(newValue, UIControlState.Normal);
|
||||
} else {
|
||||
@@ -43,7 +46,7 @@ export class TextBase extends TextBaseCommon {
|
||||
}
|
||||
set [formattedTextProperty.native](value: FormattedString) {
|
||||
const style = this.style;
|
||||
setFormattedTextDecorationAndTransform(value, this.nativeView, style.textDecoration, style.textTransform, style.letterSpacing);
|
||||
this.setFormattedTextDecorationAndTransform(value, this.nativeView, style.textDecoration, style.textTransform, style.letterSpacing);
|
||||
textProperty.nativeValueChange(this, !value ? '' : value.toString());
|
||||
this._requestLayoutOnTextChanged();
|
||||
}
|
||||
@@ -130,9 +133,9 @@ export class TextBase extends TextBaseCommon {
|
||||
this.textDecorationSet = value !== TextDecoration.NONE;
|
||||
const style = this.style;
|
||||
if (this.formattedText) {
|
||||
setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, value, style.textTransform, style.letterSpacing);
|
||||
this.setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, value, style.textTransform, style.letterSpacing);
|
||||
} else {
|
||||
setTextDecorationAndTransform(this.text, this.nativeView, value, style.textTransform, style.letterSpacing, style.color);
|
||||
this.setTextDecorationAndTransform(this.text, this.nativeView, value, style.textTransform, style.letterSpacing, style.color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,13 +147,13 @@ export class TextBase extends TextBaseCommon {
|
||||
this.textTransformSet = value !== TextTransform.NONE;
|
||||
const style = this.style;
|
||||
if (this.formattedText) {
|
||||
setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, style.textDecoration, value, style.letterSpacing);
|
||||
this.setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, style.textDecoration, value, style.letterSpacing);
|
||||
} else {
|
||||
setTextDecorationAndTransform(this.text, this.nativeView, style.textDecoration, value, style.letterSpacing, style.color);
|
||||
this.setTextDecorationAndTransform(this.text, this.nativeView, style.textDecoration, value, style.letterSpacing, style.color);
|
||||
}
|
||||
}
|
||||
|
||||
// LetterSpacing
|
||||
// LetterSpacing.
|
||||
get [letterSpacingProperty.native](): number {
|
||||
return 0;
|
||||
}
|
||||
@@ -158,11 +161,178 @@ export class TextBase extends TextBaseCommon {
|
||||
this.letterSpacingSet = value !== 0;
|
||||
const style = this.style;
|
||||
if (this.formattedText) {
|
||||
setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, style.textDecoration, style.textTransform, value);
|
||||
this.setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, style.textDecoration, style.textTransform, value);
|
||||
} else {
|
||||
setTextDecorationAndTransform(this.text, this.nativeView, style.textDecoration, style.textTransform, value, style.color);
|
||||
this.setTextDecorationAndTransform(this.text, this.nativeView, style.textDecoration, style.textTransform, value, style.color);
|
||||
}
|
||||
}
|
||||
|
||||
setFormattedTextDecorationAndTransform(formattedText: FormattedString, nativeView: UITextField | UITextView | UILabel | UIButton, textDecoration: TextDecoration, textTransform: TextTransform, letterSpacing: number) {
|
||||
const attrText = this.createNSMutableAttributedString(formattedText);
|
||||
if (letterSpacing !== 0) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
setTextDecorationAndTransform(text: string, nativeView: UITextField | UITextView | UILabel | UIButton, textDecoration: TextDecoration, textTransform: TextTransform, letterSpacing: number, color: Color) {
|
||||
let dict = new Map<string, number>();
|
||||
switch (textDecoration) {
|
||||
case TextDecoration.NONE:
|
||||
break;
|
||||
case TextDecoration.UNDERLINE:
|
||||
dict.set(NSUnderlineStyleAttributeName, NSUnderlineStyle.StyleSingle);
|
||||
break;
|
||||
case TextDecoration.LINE_THROUGH:
|
||||
dict.set(NSStrikethroughStyleAttributeName, NSUnderlineStyle.StyleSingle);
|
||||
break;
|
||||
case TextDecoration.UNDERLINE_LINE_THROUGH:
|
||||
dict.set(NSUnderlineStyleAttributeName, NSUnderlineStyle.StyleSingle);
|
||||
dict.set(NSStrikethroughStyleAttributeName, 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}".`);
|
||||
}
|
||||
|
||||
if (letterSpacing !== 0) {
|
||||
dict.set(NSKernAttributeName, letterSpacing * nativeView.font.pointSize);
|
||||
}
|
||||
|
||||
if (color) {
|
||||
dict.set(NSForegroundColorAttributeName, color.ios);
|
||||
}
|
||||
|
||||
let source = getTransformedText(text, textTransform);
|
||||
if (dict.size > 0) {
|
||||
let result = NSMutableAttributedString.alloc().initWithString(source);
|
||||
result.setAttributesRange(<any>dict, { location: 0, length: source.length });
|
||||
if (nativeView instanceof UIButton) {
|
||||
nativeView.setAttributedTitleForState(result, UIControlState.Normal);
|
||||
} else {
|
||||
nativeView.attributedText = result;
|
||||
}
|
||||
} else {
|
||||
if (nativeView instanceof UIButton) {
|
||||
// Clear attributedText or title won't be affected.
|
||||
nativeView.setAttributedTitleForState(null, UIControlState.Normal);
|
||||
nativeView.setTitleForState(source, UIControlState.Normal);
|
||||
} else {
|
||||
// Clear attributedText or text won't be affected.
|
||||
nativeView.attributedText = undefined;
|
||||
nativeView.text = source;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createNSMutableAttributedString(formattedString: FormattedString): NSMutableAttributedString {
|
||||
let mas = NSMutableAttributedString.alloc().init();
|
||||
if (formattedString) {
|
||||
for (let i = 0, spanStart = 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 !== "none") {
|
||||
spanText = getTransformedText(spanText, textTransform);
|
||||
}
|
||||
|
||||
const nsAttributedString = this.createMutableStringForSpan(span, spanText);
|
||||
mas.insertAttributedStringAtIndex(nsAttributedString, spanStart);
|
||||
spanStart += spanText.length;
|
||||
}
|
||||
}
|
||||
return mas;
|
||||
}
|
||||
|
||||
createMutableStringForSpan(span: Span, text: string): NSMutableAttributedString {
|
||||
const viewFont = this.nativeView.font;
|
||||
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) {
|
||||
if (!fontSize) {
|
||||
fontSize = viewFont.pointSize;
|
||||
}
|
||||
|
||||
if (!fontFamily) {
|
||||
fontFamily = viewFont.fontName;
|
||||
}
|
||||
|
||||
let font;
|
||||
|
||||
let fontDescriptor: UIFontDescriptor = viewFont.fontDescriptor;
|
||||
if (fontFamily) {
|
||||
fontDescriptor = fontDescriptor.fontDescriptorWithFamily(fontFamily);
|
||||
}
|
||||
|
||||
let symbolicTraits;
|
||||
if (bold) {
|
||||
symbolicTraits |= UIFontDescriptorSymbolicTraits.TraitBold;
|
||||
}
|
||||
|
||||
if (italic) {
|
||||
symbolicTraits |= UIFontDescriptorSymbolicTraits.TraitItalic;
|
||||
}
|
||||
|
||||
if (symbolicTraits) {
|
||||
font = UIFont.fontWithDescriptorSize(fontDescriptor.fontDescriptorWithSymbolicTraits(symbolicTraits), fontSize);
|
||||
} else {
|
||||
font = UIFont.fontWithDescriptorSize(fontDescriptor, fontSize);
|
||||
}
|
||||
|
||||
attrDict[NSFontAttributeName] = font;
|
||||
}
|
||||
|
||||
const color = span.color;
|
||||
if (color) {
|
||||
attrDict[NSForegroundColorAttributeName] = color.ios;
|
||||
}
|
||||
|
||||
// We don't use isSet function here because defaultValue for backgroundColor is null.
|
||||
const backgroundColor = style.backgroundColor
|
||||
|| (<FormattedString>span.parent).backgroundColor
|
||||
|| (<TextBase>(<FormattedString>span.parent).parent).backgroundColor;
|
||||
if (backgroundColor) {
|
||||
attrDict[NSBackgroundColorAttributeName] = backgroundColor.ios;
|
||||
}
|
||||
|
||||
let valueSource: typeof style;
|
||||
if (isSet(textDecorationProperty, style)) {
|
||||
valueSource = style;
|
||||
} else if (isSet(textDecorationProperty, span.parent.style)) {
|
||||
// span.parent is FormattedString
|
||||
valueSource = span.parent.style;
|
||||
} else if (isSet(textDecorationProperty, span.parent.parent.style)) {
|
||||
// span.parent.parent is TextBase
|
||||
valueSource = span.parent.parent.style;
|
||||
}
|
||||
|
||||
if (valueSource) {
|
||||
const textDecorations = valueSource.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);
|
||||
}
|
||||
}
|
||||
|
||||
export function getTransformedText(text: string, textTransform: TextTransform): string {
|
||||
@@ -184,172 +354,9 @@ function NSStringFromNSAttributedString(source: NSAttributedString | string): NS
|
||||
return NSString.stringWithString(source instanceof NSAttributedString && source.string || <string>source);
|
||||
}
|
||||
|
||||
function setFormattedTextDecorationAndTransform(formattedText: FormattedString, nativeView: UITextField | UITextView | UILabel | UIButton, textDecoration: TextDecoration, textTransform: TextTransform, letterSpacing: number) {
|
||||
const attrText = createNSMutableAttributedString(formattedText);
|
||||
if (letterSpacing !== 0) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
function setTextDecorationAndTransform(text: string, nativeView: UITextField | UITextView | UILabel | UIButton, textDecoration: TextDecoration, textTransform: TextTransform, letterSpacing: number, color: Color) {
|
||||
let dict = new Map<string, number>();
|
||||
switch (textDecoration) {
|
||||
case TextDecoration.NONE:
|
||||
break;
|
||||
case TextDecoration.UNDERLINE:
|
||||
dict.set(NSUnderlineStyleAttributeName, NSUnderlineStyle.StyleSingle);
|
||||
break;
|
||||
case TextDecoration.LINE_THROUGH:
|
||||
dict.set(NSStrikethroughStyleAttributeName, NSUnderlineStyle.StyleSingle);
|
||||
break;
|
||||
case TextDecoration.UNDERLINE_LINE_THROUGH:
|
||||
dict.set(NSUnderlineStyleAttributeName, NSUnderlineStyle.StyleSingle);
|
||||
dict.set(NSStrikethroughStyleAttributeName, 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}".`);
|
||||
}
|
||||
|
||||
if (letterSpacing !== 0) {
|
||||
dict.set(NSKernAttributeName, letterSpacing * nativeView.font.pointSize);
|
||||
}
|
||||
|
||||
if (color) {
|
||||
dict.set(NSForegroundColorAttributeName, color.ios);
|
||||
}
|
||||
|
||||
let source = getTransformedText(text, textTransform);
|
||||
if (dict.size > 0) {
|
||||
let result = NSMutableAttributedString.alloc().initWithString(source);
|
||||
result.setAttributesRange(<any>dict, { location: 0, length: source.length });
|
||||
if (nativeView instanceof UIButton) {
|
||||
nativeView.setAttributedTitleForState(result, UIControlState.Normal);
|
||||
} else {
|
||||
nativeView.attributedText = result;
|
||||
}
|
||||
} else {
|
||||
if (nativeView instanceof UIButton) {
|
||||
// Clear attributedText or title won't be affected.
|
||||
nativeView.setAttributedTitleForState(null, UIControlState.Normal);
|
||||
nativeView.setTitleForState(source, UIControlState.Normal);
|
||||
} else {
|
||||
// Clear attributedText or text won't be affected.
|
||||
nativeView.attributedText = undefined;
|
||||
nativeView.text = source;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createNSMutableAttributedString(formattedString: FormattedString): NSMutableAttributedString {
|
||||
let mas = NSMutableAttributedString.alloc().init();
|
||||
if (formattedString) {
|
||||
for (let i = 0, spanStart = 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);
|
||||
}
|
||||
|
||||
const nsAttributedString = createMutableStringForSpan(span, spanText);
|
||||
mas.insertAttributedStringAtIndex(nsAttributedString, spanStart);
|
||||
spanStart += spanText.length;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (symbolicTraits) {
|
||||
font = UIFont.fontWithDescriptorSize(fontDescriptor.fontDescriptorWithSymbolicTraits(symbolicTraits), fontSize);
|
||||
} else {
|
||||
font = UIFont.fontWithDescriptorSize(fontDescriptor, fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
attrDict[NSFontAttributeName] = font;
|
||||
}
|
||||
|
||||
const color = span.color;
|
||||
if (color) {
|
||||
attrDict[NSForegroundColorAttributeName] = color.ios;
|
||||
}
|
||||
|
||||
// We don't use isSet function here because defaultValue for backgroundColor is null.
|
||||
const backgroundColor = style.backgroundColor
|
||||
|| (<FormattedString>span.parent).backgroundColor
|
||||
|| (<TextBase>(<FormattedString>span.parent).parent).backgroundColor;
|
||||
if (backgroundColor) {
|
||||
attrDict[NSBackgroundColorAttributeName] = backgroundColor.ios;
|
||||
}
|
||||
|
||||
let valueSource: typeof style;
|
||||
if (isSet(textDecorationProperty, style)) {
|
||||
valueSource = style;
|
||||
} else if (isSet(textDecorationProperty, span.parent.style)) {
|
||||
// span.parent is FormattedString
|
||||
valueSource = span.parent.style;
|
||||
} else if (isSet(textDecorationProperty, span.parent.parent.style)) {
|
||||
// span.parent.parent is TextBase
|
||||
valueSource = span.parent.parent.style;
|
||||
}
|
||||
|
||||
if (valueSource) {
|
||||
const textDecorations = valueSource.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);
|
||||
}
|
||||
Reference in New Issue
Block a user