From d7b13299b822008829949e9b6e6cee877b48faa7 Mon Sep 17 00:00:00 2001 From: Vladimir Enchev Date: Thu, 7 Jan 2016 15:52:14 +0200 Subject: [PATCH] text-transform and text-decoration with formattedText fixed --- apps/tests/ui/style/style-properties-tests.ts | 2 +- .../decoration-transform-formattedtext.xml | 27 +++ apps/ui-tests-app/css/text-transform.xml | 24 ++- ui/button/button-common.ts | 1 + ui/button/button.ios.ts | 8 +- ui/text-base/text-base-styler.android.ts | 4 +- ui/text-base/text-base-styler.ios.ts | 8 +- utils/utils.android.ts | 30 +++- utils/utils.d.ts | 4 +- utils/utils.ios.ts | 162 ++++++++---------- 10 files changed, 157 insertions(+), 113 deletions(-) create mode 100644 apps/ui-tests-app/css/decoration-transform-formattedtext.xml diff --git a/apps/tests/ui/style/style-properties-tests.ts b/apps/tests/ui/style/style-properties-tests.ts index b37cabe4c..43c0648ad 100644 --- a/apps/tests/ui/style/style-properties-tests.ts +++ b/apps/tests/ui/style/style-properties-tests.ts @@ -591,7 +591,7 @@ export var test_setting_button_textTransform_sets_native = function () { testView.text = initial; testView.style.textTransform = enums.TextTransform.capitalize; - executeTransformTest(testView, androidText, function (v) { return (v.ios).attributedTitleForState(UIControlState.UIControlStateNormal).string; }); + executeTransformTest(testView, androidText, function (v) { return (v.ios).titleForState(UIControlState.UIControlStateNormal); }); } export var test_setting_label_textTransform_and_textDecoration_sets_native = function () { diff --git a/apps/ui-tests-app/css/decoration-transform-formattedtext.xml b/apps/ui-tests-app/css/decoration-transform-formattedtext.xml new file mode 100644 index 000000000..4be69385d --- /dev/null +++ b/apps/ui-tests-app/css/decoration-transform-formattedtext.xml @@ -0,0 +1,27 @@ + + + + \ No newline at end of file diff --git a/apps/ui-tests-app/css/text-transform.xml b/apps/ui-tests-app/css/text-transform.xml index 24190cb40..107cbea09 100644 --- a/apps/ui-tests-app/css/text-transform.xml +++ b/apps/ui-tests-app/css/text-transform.xml @@ -3,7 +3,7 @@ + \ No newline at end of file diff --git a/ui/button/button-common.ts b/ui/button/button-common.ts index 5f7192209..df471bf3c 100644 --- a/ui/button/button-common.ts +++ b/ui/button/button-common.ts @@ -111,6 +111,7 @@ export class Button extends view.View implements definition.Button { // then the property defaults to a system value. Therefore, at a minimum, you should // set the value for the normal state. this.ios.setAttributedTitleForState(value._formattedText, UIControlState.UIControlStateNormal); + this.style._updateTextDecoration(); } } diff --git a/ui/button/button.ios.ts b/ui/button/button.ios.ts index ae98a5708..f1c4ebf65 100644 --- a/ui/button/button.ios.ts +++ b/ui/button/button.ios.ts @@ -135,20 +135,20 @@ export class ButtonStyler implements style.Styler { // text-decoration private static setTextDecorationProperty(view: view.View, newValue: any) { - utils.ios.setTextDecoration((view.ios).titleLabel, newValue); + utils.ios.setTextDecorationAndTransform(view, newValue, view.style.textTransform); } private static resetTextDecorationProperty(view: view.View, nativeValue: any) { - utils.ios.setTextDecoration((view.ios).titleLabel, enums.TextDecoration.none); + utils.ios.setTextDecorationAndTransform(view, enums.TextDecoration.none, view.style.textTransform); } // text-transform private static setTextTransformProperty(view: view.View, newValue: any) { - utils.ios.setTextTransform(view.ios, newValue); + utils.ios.setTextDecorationAndTransform(view, view.style.textDecoration, newValue); } private static resetTextTransformProperty(view: view.View, nativeValue: any) { - utils.ios.setTextTransform(view.ios, enums.TextTransform.none); + utils.ios.setTextDecorationAndTransform(view, view.style.textDecoration, enums.TextTransform.none); } // white-space diff --git a/ui/text-base/text-base-styler.android.ts b/ui/text-base/text-base-styler.android.ts index 6a9e40551..12ea752d0 100644 --- a/ui/text-base/text-base-styler.android.ts +++ b/ui/text-base/text-base-styler.android.ts @@ -94,11 +94,11 @@ export class TextBaseStyler implements style.Styler { // text-transform private static setTextTransformProperty(view: view.View, newValue: any) { - utils.ad.setTextTransform(view._nativeView, newValue); + utils.ad.setTextTransform(view, newValue); } private static resetTextTransformProperty(view: view.View, nativeValue: any) { - utils.ad.setTextTransform(view._nativeView, enums.TextTransform.none); + utils.ad.setTextTransform(view, enums.TextTransform.none); } // white-space diff --git a/ui/text-base/text-base-styler.ios.ts b/ui/text-base/text-base-styler.ios.ts index 545bd7d43..30805601b 100644 --- a/ui/text-base/text-base-styler.ios.ts +++ b/ui/text-base/text-base-styler.ios.ts @@ -40,20 +40,20 @@ export class TextBaseStyler implements style.Styler { // text-decoration private static setTextDecorationProperty(view: view.View, newValue: any) { - utils.ios.setTextDecoration(view._nativeView, newValue); + utils.ios.setTextDecorationAndTransform(view, newValue, view.style.textTransform); } private static resetTextDecorationProperty(view: view.View, nativeValue: any) { - utils.ios.setTextDecoration(view._nativeView, enums.TextDecoration.none); + utils.ios.setTextDecorationAndTransform(view, enums.TextDecoration.none, view.style.textTransform); } // text-transform private static setTextTransformProperty(view: view.View, newValue: any) { - utils.ios.setTextTransform(view._nativeView, newValue); + utils.ios.setTextDecorationAndTransform(view, view.style.textDecoration, newValue); } private static resetTextTransformProperty(view: view.View, nativeValue: any) { - utils.ios.setTextTransform(view._nativeView, enums.TextTransform.none); + utils.ios.setTextDecorationAndTransform(view, view.style.textDecoration, enums.TextTransform.none); } // white-space diff --git a/utils/utils.android.ts b/utils/utils.android.ts index 213f973f4..bfd33b683 100644 --- a/utils/utils.android.ts +++ b/utils/utils.android.ts @@ -77,38 +77,52 @@ export module ad { } } - export function setTextTransform(view: android.widget.TextView, value: string) { + export function setTextTransform(v, value: string) { + let view = v._nativeView; let str = view.getText() + ""; + let result = getTransformedString(value, view, str); + + if (v.formattedText) { + for (var i = 0; i < v.formattedText.spans.length; i++) { + var span = v.formattedText.spans.getItem(i); + span.text = getTransformedString(value, view, span.text); + } + } else { + view.setText(result); + } + } + + function getTransformedString(textTransform: string, view, stringToTransform: string): string { let result: string; - switch (value) { + switch (textTransform) { case enums.TextTransform.none: default: - result = view["originalString"] || str; + result = view["originalString"] || stringToTransform; if (view["transformationMethod"]) { view.setTransformationMethod(view["transformationMethod"]); } break; case enums.TextTransform.uppercase: view.setTransformationMethod(null); - result = str.toUpperCase(); + result = stringToTransform.toUpperCase(); break; case enums.TextTransform.lowercase: view.setTransformationMethod(null); - result = str.toLowerCase(); + result = stringToTransform.toLowerCase(); break; case enums.TextTransform.capitalize: view.setTransformationMethod(null); - result = getCapitalizedString(str); + result = getCapitalizedString(stringToTransform); break; } if (!view["originalString"]) { - view["originalString"] = str; + view["originalString"] = stringToTransform; view["transformationMethod"] = view.getTransformationMethod(); } - view.setText(result); + return result; } function getCapitalizedString(str: string): string { diff --git a/utils/utils.d.ts b/utils/utils.d.ts index c85897ff1..058df7c06 100644 --- a/utils/utils.d.ts +++ b/utils/utils.d.ts @@ -145,10 +145,8 @@ * Module with ios specific utilities. */ module ios { - + export function setTextDecorationAndTransform(view: any, decoration: string, transform: string); export function setWhiteSpace(view, value: string, parentView?: any); - export function setTextTransform(view, value: string); - export function setTextDecoration(view, value: string); export function setTextAlignment(view, value: string); export interface TextUIView { diff --git a/utils/utils.ios.ts b/utils/utils.ios.ts index ce4fe1f6e..eba9c41ce 100644 --- a/utils/utils.ios.ts +++ b/utils/utils.ios.ts @@ -49,108 +49,103 @@ export module ios { } } - export function setTextDecoration(view: dts.ios.TextUIView, value: string) { - var attributes: NSMutableDictionary = NSMutableDictionary.alloc().init(); - var values = (value + "").split(" "); + export function setTextDecorationAndTransform(v: any, decoration: string, transform: string) { + if (v.formattedText) { + if (v.style.textDecoration.indexOf(enums.TextDecoration.none) === -1) { - if (values.indexOf(enums.TextDecoration.underline) !== -1) { - attributes.setObjectForKey(NSUnderlineStyle.NSUnderlineStyleSingle, NSUnderlineStyleAttributeName); - } + if (v.style.textDecoration.indexOf(enums.TextDecoration.underline) !== -1) { + (v).formattedText.underline = NSUnderlineStyle.NSUnderlineStyleSingle; + } - if (values.indexOf(enums.TextDecoration.lineThrough) !== -1) { - attributes.setObjectForKey(NSUnderlineStyle.NSUnderlineStyleSingle, NSStrikethroughStyleAttributeName); - } + if (v.style.textDecoration.indexOf(enums.TextDecoration.lineThrough) !== -1) { + (v).formattedText.strikethrough = NSUnderlineStyle.NSUnderlineStyleSingle; + } - if (values.indexOf(enums.TextDecoration.none) === -1) { - setTextDecorationNative(view, view.text || view.attributedText, attributes); + } else { + (v).formattedText.underline = NSUnderlineStyle.NSUnderlineStyleNone; + } + + for (let i = 0; i < v.formattedText.spans.length; i++) { + let span = v.formattedText.spans.getItem(i); + span.text = getTransformedText(v, span.text, transform); + console.log("HERE: " + span.text); + } } else { - setTextDecorationNative(view, view.text || view.attributedText, NSMutableDictionary.alloc().init()); + let source = v.text; + let attributes = NSMutableArray.array(); + let range = { location: 0, length: source.length }; + + var decorationValues = (decoration + "").split(" "); + + if (decorationValues.indexOf(enums.TextDecoration.none) === -1) { + let dict = NSMutableDictionary.new(); + + if (decorationValues.indexOf(enums.TextDecoration.underline) !== -1) { + dict.setValueForKey(NSUnderlineStyle.NSUnderlineStyleSingle, NSUnderlineStyleAttributeName); + } + + if (decorationValues.indexOf(enums.TextDecoration.lineThrough) !== -1) { + dict.setValueForKey(NSUnderlineStyle.NSUnderlineStyleSingle, NSStrikethroughStyleAttributeName); + } + + attributes.addObject({ attrs: dict, range: NSValue.valueWithRange(range) }); + } + + let view: dts.ios.TextUIView | UIButton = v._nativeView; + + source = getTransformedText(v, source, transform); + + if (attributes.count > 0) { + let result = NSMutableAttributedString.alloc().initWithString(source); + for (let i = 0; i < attributes.count; i++) { + result.setAttributesRange(attributes[i]["attrs"], attributes[i]["range"].rangeValue); + } + + if (view instanceof UIButton) { + (view).setAttributedTitleForState(result, UIControlState.UIControlStateNormal); + } + else { + (view).attributedText = result; + } + } else { + if (view instanceof UIButton) { + (view).setTitleForState(source, UIControlState.UIControlStateNormal); + } + else { + (view).text = source; + } + } } } - export function setTextTransform(view: dts.ios.TextUIView, value: string) { - let str = getNSStringFromView(view); - let result: string; + function getTransformedText(view, source: string, transform: string): string { + let result = source; - switch (value) { + switch (transform) { case enums.TextTransform.none: default: - result = view["originalString"] || str; + result = view["originalString"] || NSStringFromNSAttributedString(source); break; case enums.TextTransform.uppercase: - result = str.uppercaseString; + result = NSStringFromNSAttributedString(source).uppercaseString; break; case enums.TextTransform.lowercase: - result = str.lowercaseString; + result = NSStringFromNSAttributedString(source).lowercaseString; break; case enums.TextTransform.capitalize: - result = str.capitalizedString; + result = NSStringFromNSAttributedString(source).capitalizedString; break; } if (!view["originalString"]) { - view["originalString"] = str; - } - - let newStr = getAttributedStringFromView(view, result); - - if (newStr) { - setAttributedStringToView(view, newStr); - } else { - setStringToView(view, result); - } - } - - function getNSStringFromView(view: any): NSString { - let result: string; - - if (view instanceof UIButton) { - let attrTitle = (view).titleLabel.attributedText; - result = attrTitle ? attrTitle.string : (view).titleLabel.text; - } - else { - let attrText = (view).attributedText; - result = attrText ? attrText.string : (view).text; - } - - return NSString.alloc().initWithString(result || ""); - } - - function setStringToView(view: any, str: string) { - if (view instanceof UIButton) { - (view).setTitleForState(str, UIControlState.UIControlStateNormal); - } - else { - (view).text = str; - } - } - - function getAttributedStringFromView(view: any, value: string): NSMutableAttributedString { - let result: NSMutableAttributedString; - - if (view instanceof UIButton) { - let attrTitle = (view).titleLabel.attributedText; - if (attrTitle) { - result = NSMutableAttributedString.alloc().initWithAttributedString(attrTitle); - } - } else if (view.attributedText) { - result = NSMutableAttributedString.alloc().initWithAttributedString(view.attributedText); - } - - if (result) { - result.replaceCharactersInRangeWithString({ location: 0, length: result.length }, value); + view["originalString"] = NSStringFromNSAttributedString(source); } return result; } - function setAttributedStringToView(view: any, str: NSMutableAttributedString) { - if (view instanceof UIButton) { - (view).setAttributedTitleForState(str, UIControlState.UIControlStateNormal); - } - else { - (view).attributedText = str; - } + function NSStringFromNSAttributedString(source: NSAttributedString | string): NSString { + return NSString.stringWithString(source instanceof NSAttributedString && source.string || source); } export function setWhiteSpace(view: dts.ios.TextUIView, value: string, parentView?: UIView) { @@ -168,19 +163,6 @@ export module ios { } } - function setTextDecorationNative(view: dts.ios.TextUIView, value: string | NSAttributedString, attributes: NSMutableDictionary) { - var attributedString: NSMutableAttributedString; - - if (value instanceof NSAttributedString) { - attributedString = NSMutableAttributedString.alloc().initWithAttributedString(value); - attributedString.addAttributesRange(attributes, NSRangeFromString(attributedString.string)); - } else { - var types: typeof typesModule = require("utils/types"); - - view.attributedText = NSAttributedString.alloc().initWithStringAttributes(types.isString(value) ? value : "", attributes); - } - } - export module collections { export function jsArrayToNSArray(str: string[]): NSArray { return NSArray.arrayWithArray(str);