diff --git a/apps/.vscode/launch.json b/apps/.vscode/launch.json new file mode 100644 index 000000000..d2ea7615d --- /dev/null +++ b/apps/.vscode/launch.json @@ -0,0 +1,85 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch on iOS Device", + "type": "nativescript", + "platform": "ios", + "request": "launch", + "appRoot": "${workspaceRoot}", + "sourceMaps": true, + "diagnosticLogging": false, + "emulator": false + }, + { + "name": "Attach on iOS Device", + "type": "nativescript", + "platform": "ios", + "request": "attach", + "appRoot": "${workspaceRoot}", + "sourceMaps": true, + "diagnosticLogging": false, + "emulator": false + }, + { + "name": "Launch on iOS Emulator", + "type": "nativescript", + "platform": "ios", + "request": "launch", + "appRoot": "${workspaceRoot}", + "sourceMaps": true, + "diagnosticLogging": false, + "emulator": true + }, + { + "name": "Attach on iOS Emulator", + "type": "nativescript", + "platform": "ios", + "request": "attach", + "appRoot": "${workspaceRoot}", + "sourceMaps": true, + "diagnosticLogging": false, + "emulator": true + }, + { + "name": "Launch on Android Device", + "type": "nativescript", + "platform": "android", + "request": "launch", + "appRoot": "${workspaceRoot}", + "sourceMaps": true, + "diagnosticLogging": false, + "emulator": false + }, + { + "name": "Launch on Android Emulator", + "type": "nativescript", + "platform": "android", + "request": "launch", + "appRoot": "${workspaceRoot}", + "sourceMaps": true, + "diagnosticLogging": false, + "emulator": true + }, + { + "name": "Attach on Android Device", + "type": "nativescript", + "platform": "android", + "request": "attach", + "appRoot": "${workspaceRoot}", + "sourceMaps": true, + "diagnosticLogging": false, + "emulator": false + }, + { + "name": "Attach on Android Emulator", + "type": "nativescript", + "platform": "android", + "request": "attach", + "appRoot": "${workspaceRoot}", + "sourceMaps": true, + "diagnosticLogging": false, + "emulator": true + } + ] +} \ No newline at end of file diff --git a/tests/app/ui/button/button-tests.ts b/tests/app/ui/button/button-tests.ts index aa7ad9948..74eb19ec9 100644 --- a/tests/app/ui/button/button-tests.ts +++ b/tests/app/ui/button/button-tests.ts @@ -300,4 +300,68 @@ export var test_WhenFormattedTextPropertyChanges_TextIsUpdated_Button = function view.formattedText = null; TKUnit.assertEqual(view.text, ""); }); -} \ No newline at end of file +} + +export var test_IntegrationTest_Transform_Decoration_Spacing_WithoutFormattedText_DoesNotCrash = function () { + let view = new buttonModule.Button(); + helper.buildUIAndRunTest(view, function (views: Array) { + TKUnit.assertEqual(view.text, "", "Text"); + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.none, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.none, "TextDecoration"); + TKUnit.assertTrue(isNaN(view.style.letterSpacing), "LetterSpacing"); + + view.text = "NormalText"; + view.setInlineStyle("text-transform: uppercase; text-decoration: underline; letter-spacing: 10;"); + + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.uppercase, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.underline, "TextDecoration"); + TKUnit.assertEqual(view.style.letterSpacing, 10, "LetterSpacing"); + }); +} + +export var test_IntegrationTest_Transform_Decoration_Spacing_WithFormattedText_DoesNotCrash = function () { + let view = new buttonModule.Button(); + let formattedString = _generateFormattedString(); + helper.buildUIAndRunTest(view, function (views: Array) { + TKUnit.assertEqual(view.text, "", "Text"); + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.none, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.none, "TextDecoration"); + TKUnit.assertTrue(isNaN(view.style.letterSpacing), "LetterSpacing"); + + view.formattedText = formattedString; + view.setInlineStyle("text-transform: uppercase; text-decoration: underline; letter-spacing: 10;"); + + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.uppercase, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.underline, "TextDecoration"); + TKUnit.assertEqual(view.style.letterSpacing, 10, "LetterSpacing"); + }); +} + +function _generateFormattedString(): formattedStringModule.FormattedString{ + let formattedString = new formattedStringModule.FormattedString(); + let span: spanModule.Span; + + span = new spanModule.Span(); + span.fontFamily = "serif"; + span.fontSize = 10; + span.fontAttributes = enums.FontAttributes.Bold; + span.foregroundColor = new colorModule.Color("red"); + span.backgroundColor = new colorModule.Color("blue"); + span.underline = 0; + span.strikethrough = 1; + span.text = "Formatted"; + formattedString.spans.push(span); + + span = new spanModule.Span(); + span.fontFamily = "sans-serif"; + span.fontSize = 20; + span.fontAttributes = enums.FontAttributes.Italic; + span.foregroundColor = new colorModule.Color("green"); + span.backgroundColor = new colorModule.Color("yellow"); + span.underline = 1; + span.strikethrough = 0; + span.text = "Text"; + formattedString.spans.push(span); + + return formattedString; +} diff --git a/tests/app/ui/label/label-tests.ts b/tests/app/ui/label/label-tests.ts index 09e4bfbf7..7d03c3c63 100644 --- a/tests/app/ui/label/label-tests.ts +++ b/tests/app/ui/label/label-tests.ts @@ -22,6 +22,9 @@ import {isIOS} from "platform"; import {Label} from "ui/label"; import {LayoutBase} from "ui/layouts/layout-base"; import * as helper from "../helper"; +import viewModule = require("ui/core/view"); +import formattedStringModule = require("text/formatted-string"); +import spanModule = require("text/span"); export class LabelTest extends testModule.UITest { @@ -596,3 +599,66 @@ export function createTestCase(): LabelTest { return new LabelTest(); } +export var test_IntegrationTest_Transform_Decoration_Spacing_WithoutFormattedText_DoesNotCrash = function () { + let view = new LabelModule.Label(); + helper.buildUIAndRunTest(view, function (views: Array) { + TKUnit.assertEqual(view.text, "", "Text"); + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.none, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.none, "TextDecoration"); + TKUnit.assertTrue(isNaN(view.style.letterSpacing), "LetterSpacing"); + + view.text = "NormalText"; + view.setInlineStyle("text-transform: uppercase; text-decoration: underline; letter-spacing: 10;"); + + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.uppercase, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.underline, "TextDecoration"); + TKUnit.assertEqual(view.style.letterSpacing, 10, "LetterSpacing"); + }); +} + +export var test_IntegrationTest_Transform_Decoration_Spacing_WithFormattedText_DoesNotCrash = function () { + let view = new LabelModule.Label(); + let formattedString = _generateFormattedString(); + helper.buildUIAndRunTest(view, function (views: Array) { + TKUnit.assertEqual(view.text, "", "Text"); + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.none, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.none, "TextDecoration"); + TKUnit.assertTrue(isNaN(view.style.letterSpacing), "LetterSpacing"); + + view.formattedText = formattedString; + view.setInlineStyle("text-transform: uppercase; text-decoration: underline; letter-spacing: 10;"); + + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.uppercase, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.underline, "TextDecoration"); + TKUnit.assertEqual(view.style.letterSpacing, 10, "LetterSpacing"); + }); +} + +function _generateFormattedString(): formattedStringModule.FormattedString{ + let formattedString = new formattedStringModule.FormattedString(); + let span: spanModule.Span; + + span = new spanModule.Span(); + span.fontFamily = "serif"; + span.fontSize = 10; + span.fontAttributes = enums.FontAttributes.Bold; + span.foregroundColor = new colorModule.Color("red"); + span.backgroundColor = new colorModule.Color("blue"); + span.underline = 0; + span.strikethrough = 1; + span.text = "Formatted"; + formattedString.spans.push(span); + + span = new spanModule.Span(); + span.fontFamily = "sans-serif"; + span.fontSize = 20; + span.fontAttributes = enums.FontAttributes.Italic; + span.foregroundColor = new colorModule.Color("green"); + span.backgroundColor = new colorModule.Color("yellow"); + span.underline = 1; + span.strikethrough = 0; + span.text = "Text"; + formattedString.spans.push(span); + + return formattedString; +} diff --git a/tests/app/ui/text-field/text-field-tests.ts b/tests/app/ui/text-field/text-field-tests.ts index 85080ba31..caba3ef6c 100644 --- a/tests/app/ui/text-field/text-field-tests.ts +++ b/tests/app/ui/text-field/text-field-tests.ts @@ -535,3 +535,67 @@ export var test_WhenFormattedTextPropertyChanges_TextIsUpdated_TextBase = functi TKUnit.assertEqual(view.text, ""); }); } + +export var test_IntegrationTest_Transform_Decoration_Spacing_WithoutFormattedText_DoesNotCrash = function () { + let view = new textFieldModule.TextField(); + helper.buildUIAndRunTest(view, function (views: Array) { + TKUnit.assertEqual(view.text, "", "Text"); + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.none, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.none, "TextDecoration"); + TKUnit.assertTrue(isNaN(view.style.letterSpacing), "LetterSpacing"); + + view.text = "NormalText"; + view.setInlineStyle("text-transform: uppercase; text-decoration: underline; letter-spacing: 10;"); + + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.uppercase, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.underline, "TextDecoration"); + TKUnit.assertEqual(view.style.letterSpacing, 10, "LetterSpacing"); + }); +} + +export var test_IntegrationTest_Transform_Decoration_Spacing_WithFormattedText_DoesNotCrash = function () { + let view = new textFieldModule.TextField(); + let formattedString = _generateFormattedString(); + helper.buildUIAndRunTest(view, function (views: Array) { + TKUnit.assertEqual(view.text, "", "Text"); + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.none, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.none, "TextDecoration"); + TKUnit.assertTrue(isNaN(view.style.letterSpacing), "LetterSpacing"); + + view.formattedText = formattedString; + view.setInlineStyle("text-transform: uppercase; text-decoration: underline; letter-spacing: 10;"); + + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.uppercase, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.underline, "TextDecoration"); + TKUnit.assertEqual(view.style.letterSpacing, 10, "LetterSpacing"); + }); +} + +function _generateFormattedString(): formattedStringModule.FormattedString{ + let formattedString = new formattedStringModule.FormattedString(); + let span: spanModule.Span; + + span = new spanModule.Span(); + span.fontFamily = "serif"; + span.fontSize = 10; + span.fontAttributes = enums.FontAttributes.Bold; + span.foregroundColor = new colorModule.Color("red"); + span.backgroundColor = new colorModule.Color("blue"); + span.underline = 0; + span.strikethrough = 1; + span.text = "Formatted"; + formattedString.spans.push(span); + + span = new spanModule.Span(); + span.fontFamily = "sans-serif"; + span.fontSize = 20; + span.fontAttributes = enums.FontAttributes.Italic; + span.foregroundColor = new colorModule.Color("green"); + span.backgroundColor = new colorModule.Color("yellow"); + span.underline = 1; + span.strikethrough = 0; + span.text = "Text"; + formattedString.spans.push(span); + + return formattedString; +} diff --git a/tests/app/ui/text-view/text-view-tests.ts b/tests/app/ui/text-view/text-view-tests.ts index f03186e0f..38607e9a2 100644 --- a/tests/app/ui/text-view/text-view-tests.ts +++ b/tests/app/ui/text-view/text-view-tests.ts @@ -6,6 +6,8 @@ import textViewTestsNative = require("./text-view-tests-native"); import colorModule = require("color"); import enums = require("ui/enums"); import platform = require("platform"); +import formattedStringModule = require("text/formatted-string"); +import spanModule = require("text/span"); // >> require-textmodules import textViewModule = require("ui/text-view"); @@ -494,3 +496,67 @@ export function test_watch_listerer_is_removed_at_onDetach() { }); } } + +export var test_IntegrationTest_Transform_Decoration_Spacing_WithoutFormattedText_DoesNotCrash = function () { + let view = new textViewModule.TextView(); + helper.buildUIAndRunTest(view, function (views: Array) { + TKUnit.assertEqual(view.text, "", "Text"); + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.none, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.none, "TextDecoration"); + TKUnit.assertTrue(isNaN(view.style.letterSpacing), "LetterSpacing"); + + view.text = "NormalText"; + view.setInlineStyle("text-transform: uppercase; text-decoration: underline; letter-spacing: 10;"); + + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.uppercase, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.underline, "TextDecoration"); + TKUnit.assertEqual(view.style.letterSpacing, 10, "LetterSpacing"); + }); +} + +export var test_IntegrationTest_Transform_Decoration_Spacing_WithFormattedText_DoesNotCrash = function () { + let view = new textViewModule.TextView(); + let formattedString = _generateFormattedString(); + helper.buildUIAndRunTest(view, function (views: Array) { + TKUnit.assertEqual(view.text, "", "Text"); + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.none, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.none, "TextDecoration"); + TKUnit.assertTrue(isNaN(view.style.letterSpacing), "LetterSpacing"); + + view.formattedText = formattedString; + view.setInlineStyle("text-transform: uppercase; text-decoration: underline; letter-spacing: 10;"); + + TKUnit.assertEqual(view.style.textTransform, enums.TextTransform.uppercase, "TextTransform"); + TKUnit.assertEqual(view.style.textDecoration, enums.TextDecoration.underline, "TextDecoration"); + TKUnit.assertEqual(view.style.letterSpacing, 10, "LetterSpacing"); + }); +} + +function _generateFormattedString(): formattedStringModule.FormattedString{ + let formattedString = new formattedStringModule.FormattedString(); + let span: spanModule.Span; + + span = new spanModule.Span(); + span.fontFamily = "serif"; + span.fontSize = 10; + span.fontAttributes = enums.FontAttributes.Bold; + span.foregroundColor = new colorModule.Color("red"); + span.backgroundColor = new colorModule.Color("blue"); + span.underline = 0; + span.strikethrough = 1; + span.text = "Formatted"; + formattedString.spans.push(span); + + span = new spanModule.Span(); + span.fontFamily = "sans-serif"; + span.fontSize = 20; + span.fontAttributes = enums.FontAttributes.Italic; + span.foregroundColor = new colorModule.Color("green"); + span.backgroundColor = new colorModule.Color("yellow"); + span.underline = 1; + span.strikethrough = 0; + span.text = "Text"; + formattedString.spans.push(span); + + return formattedString; +} diff --git a/tns-core-modules/text/formatted-string-common.ts b/tns-core-modules/text/formatted-string-common.ts index 9a7d6c225..6ecc51c36 100644 --- a/tns-core-modules/text/formatted-string-common.ts +++ b/tns-core-modules/text/formatted-string-common.ts @@ -234,4 +234,8 @@ export class FormattedString extends observable.Observable implements definition view.formattedText = value; } } + + public _updateCharactersInRangeReplacementString(rangeLocation: number, rangeLength: number, replacementString: string): void { + // + } } \ No newline at end of file diff --git a/tns-core-modules/text/formatted-string.d.ts b/tns-core-modules/text/formatted-string.d.ts index f6711c365..8c0c323ca 100644 --- a/tns-core-modules/text/formatted-string.d.ts +++ b/tns-core-modules/text/formatted-string.d.ts @@ -97,6 +97,11 @@ declare module "text/formatted-string" { /** * A static method used to add child elements of the FormattedString class to a View declared in xml. */ - public static addFormattedStringToView(view: FormattedStringView, name: string, value: any): void; + public static addFormattedStringToView(view: FormattedStringView, name: string, value: any): void; + + //@private + createFormattedStringCore(): void; + _updateCharactersInRangeReplacementString(rangeLocation: number, rangeLength: number, replacementString: string): void; + //@endprivate } } \ No newline at end of file diff --git a/tns-core-modules/text/formatted-string.ios.ts b/tns-core-modules/text/formatted-string.ios.ts index cde590c76..81fe23d14 100644 --- a/tns-core-modules/text/formatted-string.ios.ts +++ b/tns-core-modules/text/formatted-string.ios.ts @@ -27,4 +27,29 @@ export class FormattedString extends formattedStringCommon.FormattedString { } this._formattedText = mas; } + + public _updateCharactersInRangeReplacementString(rangeLocation: number, rangeLength: number, replacementString: string): void { + let deletingText = !replacementString; + let currentLocation = 0; + for (let i = 0; i < this.spans.length; i++) { + let span = this.spans.getItem(i); + if (currentLocation <= rangeLocation && rangeLocation < (currentLocation + span.text.length)){ + (span)._text = splice(span.text, rangeLocation - currentLocation, deletingText ? rangeLength : 0, replacementString); + //console.log(`>>> ${span.text}`); + return; + } + currentLocation += span.text.length; + } + } } + +/* + * @param {String} value The string to splice. + * @param {number} start Index at which to start changing the string. + * @param {number} delCount An integer indicating the number of old chars to remove. + * @param {string} newSubStr The String that is spliced in. + * @return {string} A new string with the spliced substring.function splice(value: string, start: number, delCount: number, newSubStr: string) { + */ +function splice(value: string, start: number, delCount: number, newSubStr: string) { + return value.slice(0, start) + newSubStr + value.slice(start + Math.abs(delCount)); +}; \ No newline at end of file diff --git a/tns-core-modules/ui/button/button-common.ts b/tns-core-modules/ui/button/button-common.ts index edf7dd924..4657e23ed 100644 --- a/tns-core-modules/ui/button/button-common.ts +++ b/tns-core-modules/ui/button/button-common.ts @@ -28,6 +28,7 @@ function onTextPropertyChanged(data: PropertyChangeData) { button._onTextPropertyChanged(data); + //RemoveThisDoubleCall button.style._updateTextDecoration(); button.style._updateTextTransform(); } @@ -53,6 +54,8 @@ export class Button extends view.View implements definition.Button { this.formattedText.updateSpansBindingContext(newValue); } + //This is because of ListView virtualization + //RemoveThisDoubleCall this.style._updateTextDecoration(); this.style._updateTextTransform(); } diff --git a/tns-core-modules/ui/button/button.ios.ts b/tns-core-modules/ui/button/button.ios.ts index a1ecb7c54..3ff0fa1eb 100644 --- a/tns-core-modules/ui/button/button.ios.ts +++ b/tns-core-modules/ui/button/button.ios.ts @@ -6,6 +6,7 @@ import view = require("ui/core/view"); import utils = require("utils/utils"); import enums = require("ui/enums"); import dependencyObservable = require("ui/core/dependency-observable"); +import types = require("utils/types"); import {PseudoClassHandler} from "ui/core/view"; class TapHandlerImpl extends NSObject { @@ -63,7 +64,9 @@ export class Button extends common.Button { // set the value for the normal state. let newText = value ? value._formattedText : null; this.ios.setAttributedTitleForState(newText, UIControlState.UIControlStateNormal); + //RemoveThisDoubleCall this.style._updateTextDecoration(); + this.style._updateTextTransform(); } @PseudoClassHandler("normal", "highlighted") @@ -164,29 +167,29 @@ export class ButtonStyler implements style.Styler { // text-decoration private static setTextDecorationProperty(view: view.View, newValue: any) { - utils.ios.setTextDecorationAndTransform(view, newValue, view.style.textTransform, view.style.letterSpacing); + ButtonStyler._setButtonTextDecorationAndTransform(