Total TextBase refactoring + several bug fixes.

This commit is contained in:
Rossen Hristov
2016-12-16 14:53:27 +02:00
parent c8e13c23f0
commit 93d4fa5d57
15 changed files with 434 additions and 653 deletions

View File

@@ -1,5 +1,5 @@
import { Button as ButtonDefinition } from "ui/button";
import { TextBase } from "ui/text-base";
import { TextBase, WhiteSpace } from "ui/text-base";
export * from "ui/text-base";
@@ -7,9 +7,9 @@ export abstract class ButtonBase extends TextBase implements ButtonDefinition {
public static tapEvent = "tap";
get textWrap(): boolean {
return this.style.whiteSpace === "normal";
return this.style.whiteSpace === WhiteSpace.NORMAL;
}
set textWrap(value: boolean) {
this.style.whiteSpace = value ? "normal" : "nowrap";
this.style.whiteSpace = value ? WhiteSpace.NORMAL : WhiteSpace.NO_WRAP;
}
}

View File

@@ -1,6 +1,6 @@
import {
ButtonBase, textProperty, formattedTextProperty, TouchGestureEventData, FormattedString, GestureTypes, TouchAction,
PseudoClassHandler
PseudoClassHandler, TextTransform
} from "./button-common";
export * from "./button-common";
@@ -23,7 +23,6 @@ class ClickListener extends java.lang.Object implements android.view.View.OnClic
export class Button extends ButtonBase {
_button: android.widget.Button;
private _isPressed: boolean;
private _transformationMethod;
private _highlightedHandler: (args: TouchGestureEventData) => void;
get android(): android.widget.Button {
@@ -36,22 +35,6 @@ export class Button extends ButtonBase {
this._button.setOnClickListener(new ClickListener(weakRef));
}
public _setFormattedTextPropertyToNative(value: FormattedString) {
let newText = value ? value._formattedText : null;
if (newText) {
if (!this._transformationMethod) {
this._transformationMethod = this.android.getTransformationMethod();
}
this.android.setTransformationMethod(null);
} else {
if (this._transformationMethod && !this.android.getTransformationMethod()) {
this.android.setTransformationMethod(this._transformationMethod);
}
}
this._button.setText(newText);
}
@PseudoClassHandler("normal", "highlighted", "pressed", "active")
_updateHandler(subscribe: boolean) {
if (subscribe) {

View File

@@ -2,7 +2,7 @@
import {
View, ButtonBase, PseudoClassHandler, textProperty, formattedTextProperty, whiteSpaceProperty,
borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty,
paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty, Length
paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty, Length, WhiteSpace
} from "./button-common";
export * from "./button-common";
@@ -42,18 +42,22 @@ export class Button extends ButtonBase {
}
}
get [whiteSpaceProperty.native](): "normal" | "nowrap" {
return "normal";
get [whiteSpaceProperty.native](): WhiteSpace {
return WhiteSpace.NORMAL;
}
set [whiteSpaceProperty.native](value: "normal" | "nowrap") {
set [whiteSpaceProperty.native](value: WhiteSpace) {
let nativeView = this.nativeView.titleLabel;
if (value === "normal") {
switch(value){
case WhiteSpace.NORMAL:
nativeView.lineBreakMode = NSLineBreakMode.ByWordWrapping;
nativeView.numberOfLines = 0;
}
else {
break;
case WhiteSpace.NO_WRAP:
nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
nativeView.numberOfLines = 1;
break;
default:
throw new Error(`Invalid whitespace value: ${value}. Valid values are: "${WhiteSpace.NORMAL}", "${WhiteSpace.NO_WRAP}".`);
}
}

View File

@@ -1,5 +1,5 @@
import { Label as LabelDefinition } from "ui/label";
import { TextBase } from "ui/text-base";
import { TextBase, WhiteSpace } from "ui/text-base";
export * from "ui/text-base";
@@ -7,10 +7,10 @@ export class Label extends TextBase implements LabelDefinition {
private _android: android.widget.TextView;
get textWrap(): boolean {
return this.style.whiteSpace === "normal";
return this.style.whiteSpace === WhiteSpace.NORMAL;
}
set textWrap(value: boolean) {
this.style.whiteSpace = value ? "normal" : "nowrap";
this.style.whiteSpace = value ? WhiteSpace.NORMAL : WhiteSpace.NO_WRAP;
}
get android(): android.widget.TextView {

View File

@@ -3,7 +3,7 @@ import {
Background, TextBase, View, layout, backgroundInternalProperty,
borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty,
paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty, whiteSpaceProperty,
Length
Length, WhiteSpace
} from "ui/text-base";
import { ios } from "ui/styling/background";
@@ -42,10 +42,10 @@ export class Label extends TextBase implements LabelDefinition {
}
get textWrap(): boolean {
return this.style.whiteSpace === "normal";
return this.style.whiteSpace === WhiteSpace.NORMAL;
}
set textWrap(value: boolean) {
this.style.whiteSpace = value ? "normal" : "nowrap";
this.style.whiteSpace = value ? WhiteSpace.NORMAL : WhiteSpace.NO_WRAP;
}
public onLoaded() {
@@ -86,7 +86,7 @@ export class Label extends TextBase implements LabelDefinition {
let nativeSize = nativeView.sizeThatFits(CGSizeMake(width, height));
let labelWidth = nativeSize.width;
if (!this.textWrap && this.style.whiteSpace !== "nowrap") {
if (this.textWrap) {
labelWidth = Math.min(labelWidth, width);
}
@@ -101,18 +101,22 @@ export class Label extends TextBase implements LabelDefinition {
}
}
get [whiteSpaceProperty.native](): "nowrap" | "normal" {
return "normal";
get [whiteSpaceProperty.native](): WhiteSpace {
return WhiteSpace.NORMAL;
}
set [whiteSpaceProperty.native](value: string) {
set [whiteSpaceProperty.native](value: WhiteSpace) {
let nativeView = this.nativeView;
if (value === "normal") {
switch(value){
case WhiteSpace.NORMAL:
nativeView.lineBreakMode = NSLineBreakMode.ByWordWrapping;
nativeView.numberOfLines = 0;
}
else {
break;
case WhiteSpace.NO_WRAP:
nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
nativeView.numberOfLines = 1;
break;
default:
throw new Error(`Invalid whitespace value: ${value}. Valid values are: "${WhiteSpace.NORMAL}", "${WhiteSpace.NO_WRAP}".`);
}
}

View File

@@ -15,54 +15,6 @@ export function fontSizeConverter(value: string): number {
return floatConverter(value);
}
export function textAlignConverter(value: string): string {
switch (value) {
case "left":
case "center":
case "right":
return value;
default:
throw new Error("CSS text-align \"" + value + "\" is not supported.");
}
}
export function textDecorationConverter(value: string): string {
const values = (value + "").split(" ");
if (values.indexOf("none") !== -1
|| values.indexOf("underline") !== -1
|| values.indexOf("line-through") !== -1
|| values.indexOf("underline line-through") !== -1
|| values.indexOf("line-through underline") !== -1
) {
return value;
} else {
throw new Error("CSS text-decoration \"" + value + "\" is not supported.");
}
}
export function whiteSpaceConverter(value: string): string {
switch (value) {
case "normal":
case "nowrap":
return value;
default:
throw new Error("CSS white-space \"" + value + "\" is not supported.");
}
}
export function textTransformConverter(value: string): string {
switch (value) {
case "none":
case "uppercase":
case "lowercase":
case "capitalize":
return value;
default:
throw new Error("CSS text-transform \"" + value + "\" is not supported.");
}
}
export const numberConverter = parseFloat;
export function visibilityConverter(value: string): string {

View File

@@ -1,6 +1,6 @@
declare module "ui/styling/style" {
import { Length, PercentLength, Color, Background, Font, ViewBase, Observable } from "ui/core/view";
import { TextDecoration } from "ui/text-base";
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from "ui/text-base";
export interface Thickness {
left: number;
@@ -86,10 +86,10 @@ declare module "ui/styling/style" {
public visibility: "visible" | "hidden" | "collapse" | "collapsed";
public letterSpacing: number;
public textAlignment: "left" | "center" | "right";
public textAlignment: TextAlignment;
public textDecoration: TextDecoration;
public textTransform: "none" | "capitalize" | "uppercase" | "lowercase";
public whiteSpace: "normal" | "nowrap";
public textTransform: TextTransform;
public whiteSpace: WhiteSpace;
public minWidth: Length;
public minHeight: Length;

View File

@@ -8,7 +8,7 @@ import {
Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf
} from "ui/layouts/flexbox-layout";
import { TextDecoration } from "ui/text-base";
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from "ui/text-base";
export class Style extends Observable implements StyleDefinition {
constructor(public view: ViewBase) {
@@ -65,10 +65,10 @@ export class Style extends Observable implements StyleDefinition {
public visibility: "visible" | "hidden" | "collapse" | "collapsed";
public letterSpacing: number;
public textAlignment: "left" | "center" | "right";
public textAlignment: TextAlignment;
public textDecoration: TextDecoration;
public textTransform: "none" | "capitalize" | "uppercase" | "lowercase";
public whiteSpace: "normal" | "nowrap";
public textTransform: TextTransform;
public whiteSpace: WhiteSpace;
public minWidth: Length;
public minHeight: Length;

View File

@@ -7,30 +7,6 @@ import { addWeakEventListener, removeWeakEventListener } from "ui/core/weak-even
export { FormattedString };
export * from "ui/core/view";
function onFormattedTextPropertyChanged(textBase: TextBaseCommon, oldValue: FormattedString, newValue: FormattedString) {
if (oldValue) {
oldValue.parent = null;
removeWeakEventListener(oldValue, Observable.propertyChangeEvent, textBase.onFormattedTextChanged, textBase);
}
if (newValue) {
newValue.parent = textBase;
addWeakEventListener(newValue, Observable.propertyChangeEvent, textBase.onFormattedTextChanged, textBase);
}
// textBase._onFormattedTextPropertyChanged(newValue);
}
function onTextPropertyChanged(textBase: TextBaseCommon, oldValue: string, newValue: string) {
// textBase._onTextPropertyChanged(newValue);
// //RemoveThisDoubleCall
// textBase.style._updateTextTransform();
// textBase.style._updateTextDecoration();
}
// (<proxy.PropertyMetadata>textProperty.metadata).onSetNativeValue = onTextPropertyChanged;
// (<proxy.PropertyMetadata>formattedTextProperty.metadata).onSetNativeValue = onFormattedTextPropertyChanged;
export abstract class TextBaseCommon extends View implements TextBaseDefinition, FormattedStringView {
constructor() {
@@ -39,24 +15,11 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition,
this.formattedText = new FormattedString();
}
public abstract _setFormattedTextPropertyToNative(value): void;
// public _onBindingContextChanged(oldValue: any, newValue: any) {
// super._onBindingContextChanged(oldValue, newValue);
// if (this.formattedText) {
// this.formattedText.updateSpansBindingContext(newValue);
// }
// //This is because of ListView virtualization
// //RemoveThisDoubleCall
// this.style._updateTextTransform();
// this.style._updateTextDecoration();
// }
public abstract _setFormattedTextPropertyToNative(value: FormattedString): void;
public text: string;
public formattedText: FormattedString;
// TODO: Do we need to export these properties here??
get fontSize(): number {
return this.style.fontSize;
}
@@ -71,10 +34,10 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition,
this.style.letterSpacing = value;
}
get textAlignment(): "left" | "center" | "right" {
get textAlignment(): TextAlignment {
return this.style.textAlignment;
}
set textAlignment(value: "left" | "center" | "right") {
set textAlignment(value: TextAlignment) {
this.style.textAlignment = value;
}
@@ -85,17 +48,17 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition,
this.style.textDecoration = value;
}
get textTransform(): "none" | "capitalize" | "uppercase" | "lowercase" {
get textTransform(): TextTransform {
return this.style.textTransform;
}
set textTransform(value: "none" | "capitalize" | "uppercase" | "lowercase") {
set textTransform(value: TextTransform) {
this.style.textTransform = value;
}
get whiteSpace(): "normal" | "nowrap" {
get whiteSpace(): WhiteSpace {
return this.style.whiteSpace;
}
set whiteSpace(value: "normal" | "nowrap") {
set whiteSpace(value: WhiteSpace) {
this.style.whiteSpace = value;
}
@@ -114,28 +77,40 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition,
}
}
//Text
export const textProperty = new Property<TextBaseCommon, string>({ name: "text", defaultValue: "" });
textProperty.register(TextBaseCommon);
//FormattedText
export const formattedTextProperty = new Property<TextBaseCommon, FormattedString>({ name: "formattedText", affectsLayout: isIOS, valueChanged: onFormattedTextPropertyChanged });
formattedTextProperty.register(TextBaseCommon);
export const textAlignmentProperty = new InheritedCssProperty<Style, "left" | "center" | "right">({
name: "textAlignment", cssName: "text-align", valueConverter: (value) => {
switch (value) {
case "left":
case "center":
case "right":
return <"left" | "center" | "right">value;
function onFormattedTextPropertyChanged(textBase: TextBaseCommon, oldValue: FormattedString, newValue: FormattedString) {
if (oldValue) {
oldValue.parent = null;
removeWeakEventListener(oldValue, Observable.propertyChangeEvent, textBase.onFormattedTextChanged, textBase);
}
default:
throw new Error(`CSS text-align ${value} is not supported.`);
if (newValue) {
newValue.parent = textBase;
addWeakEventListener(newValue, Observable.propertyChangeEvent, textBase.onFormattedTextChanged, textBase);
}
}
});
}
//TextAlignment
export type TextAlignment = "left" | "center" | "right";
export namespace TextAlignment {
export const LEFT: "left" = "left";
export const CENTER: "center" = "center";
export const RIGHT: "right" = "right";
export const isValid = makeValidator<TextAlignment>(LEFT, CENTER, RIGHT);
export const parse = makeParser(isValid, undefined);
}
export const textAlignmentProperty = new InheritedCssProperty<Style, TextAlignment>({name: "textAlignment", cssName: "text-align", valueConverter: TextAlignment.parse});
textAlignmentProperty.register(Style);
// TextDecoration
//TextDecoration
export type TextDecoration = "none" | "underline" | "line-through" | "underline line-through";
export namespace TextDecoration {
export const NONE: "none" = "none";
@@ -146,37 +121,32 @@ export namespace TextDecoration {
export const isValid = makeValidator<TextDecoration>(NONE, UNDERLINE, LINE_THROUGH, UNDERLINE_LINE_THROUGH);
export const parse = makeParser(isValid, NONE);
}
export const textDecorationProperty = new CssProperty<Style, TextDecoration>({
name: "textDecoration", cssName: "text-decoration", defaultValue: TextDecoration.NONE, valueConverter: TextDecoration.parse});
export const textDecorationProperty = new CssProperty<Style, TextDecoration>({name: "textDecoration", cssName: "text-decoration", defaultValue: TextDecoration.NONE, valueConverter: TextDecoration.parse});
textDecorationProperty.register(Style);
export const textTransformProperty = new CssProperty<Style, "none" | "capitalize" | "uppercase" | "lowercase">({
name: "textTransform", cssName: "text-transform", defaultValue: "none", valueConverter: (value) => {
switch (value) {
case "none":
case "uppercase":
case "lowercase":
case "capitalize":
return <"none" | "capitalize" | "uppercase" | "lowercase">value;
default:
throw new Error(`CSS text-transform ${value} is not supported.`);
}
}
});
//TextTransform
export type TextTransform = "none" | "capitalize" | "uppercase" | "lowercase";
export namespace TextTransform {
export const NONE: "none" = "none";
export const CAPITALIZE: "capitalize" = "capitalize";
export const UPPERCASE: "uppercase" = "uppercase";
export const LOWERCASE: "lowercase" ="lowercase";
export const isValid = makeValidator<TextTransform>(NONE, CAPITALIZE, UPPERCASE, LOWERCASE);
export const parse = makeParser(isValid, NONE);
}
export const textTransformProperty = new CssProperty<Style, TextTransform>({name: "textTransform", cssName: "text-transform", defaultValue: TextTransform.NONE, valueConverter: TextTransform.parse});
textTransformProperty.register(Style);
export const whiteSpaceProperty = new CssProperty<Style, "normal" | "nowrap">({
name: "whiteSpace", cssName: "white-space", valueConverter: (value: "normal" | "nowrap") => {
switch (value) {
case "normal":
case "nowrap":
return value;
default:
throw new Error(`CSS white-space ${value} is not supported.`);
}
}
});
//Whitespace
export type WhiteSpace = "normal" | "nowrap";
export namespace WhiteSpace {
export const NORMAL: "normal" = "normal";
export const NO_WRAP: "nowrap" = "nowrap";
export const isValid = makeValidator<WhiteSpace>(NORMAL, NO_WRAP);
export const parse = makeParser(isValid, NORMAL);
}
export const whiteSpaceProperty = new CssProperty<Style, WhiteSpace>({name: "whiteSpace", cssName: "white-space", defaultValue: WhiteSpace.NORMAL, valueConverter: WhiteSpace.parse});
whiteSpaceProperty.register(Style);
export const letterSpacingProperty = new CssProperty<Style, number>({ name: "letterSpacing", cssName: "letter-spacing", defaultValue: 0, affectsLayout: isIOS, valueConverter: (v: string) => parseFloat(v) });

View File

@@ -1,83 +1,15 @@
import {
TextBaseCommon, textProperty, formattedTextProperty, textAlignmentProperty, textDecorationProperty,
textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty, whiteSpaceProperty,
Font, Color, FormattedString, TextDecoration
Font, Color, FormattedString, TextDecoration, TextAlignment, TextTransform, WhiteSpace
} from "./text-base-common";
export * from "./text-base-common";
function getCapitalizedString(str: string): string {
let words = str.split(" ");
let newWords = [];
for (let i = 0, length = words.length; i < length; i++) {
let word = words[i].toLowerCase();
newWords.push(word.substr(0, 1).toUpperCase() + word.substring(1));
}
return newWords.join(" ");
}
export function getTransformedText(text: string, transform: "none" | "capitalize" | "uppercase" | "lowercase"): string {
switch (transform) {
case "uppercase":
return text.toUpperCase();
case "lowercase":
return text.toLowerCase();
case "capitalize":
return getCapitalizedString(text);
default:
return text;
}
}
@Interfaces([android.text.method.TransformationMethod])
class TextTransformation extends android.text.method.ReplacementTransformationMethod {
constructor(public originalText: string, public formattedText: FormattedString, public textTransform: "none" | "capitalize" | "uppercase" | "lowercase") {
super();
return global.__native(this);
}
protected getOriginal(): native.Array<string> {
return this.formattedText ? this.formattedText._formattedText : this.originalText;
}
protected getReplacement(): native.Array<string> {
let result: string = "";
let textTransform = this.textTransform
if (this.formattedText) {
for (let i = 0, length = this.formattedText.spans.length; i < length; i++) {
let span = this.formattedText.spans.getItem(i);
result += getTransformedText(span.text, textTransform);
// span.text = formatString(span.text, this.textTransform);
}
} else {
result = getTransformedText(this.originalText, textTransform);
}
return result;
}
}
export class TextBase extends TextBaseCommon {
_transformationMethod: any;
_nativeView: android.widget.TextView;
public _setFormattedTextPropertyToNative(value: FormattedString) {
// TODO: Check if there is an option to force call the transformation method without
// creating new native instance.
if (this._nativeView) {
this._nativeView.setTransformationMethod(new TextTransformation(this.text, value, this.style.textTransform));
}
let newText = value ? value._formattedText : null;
if (this._nativeView) {
this._nativeView.setText(newText);
}
}
//Text
get [textProperty.native](): string {
return this._nativeView.getText();
}
@@ -89,6 +21,7 @@ export class TextBase extends TextBaseCommon {
this._nativeView.setText(value);
}
//FormattedText
get [formattedTextProperty.native](): FormattedString {
return null;
}
@@ -96,6 +29,7 @@ export class TextBase extends TextBaseCommon {
this._setFormattedTextPropertyToNative(value);
}
//Color
get [colorProperty.native](): android.content.res.ColorStateList {
return this._nativeView.getTextColors();
}
@@ -107,6 +41,7 @@ export class TextBase extends TextBaseCommon {
}
}
//FontInternal
get [fontInternalProperty.native](): { typeface: android.graphics.Typeface, fontSize: number } {
let textView = this._nativeView;
return {
@@ -130,74 +65,118 @@ export class TextBase extends TextBaseCommon {
textView.setTypeface(typeface);
}
get [textAlignmentProperty.native](): string {
let textGravity = this._nativeView.getGravity() & android.view.View.TEXT_ALIGNMENT_GRAVITY;
switch (textGravity) {
//TextAlignment
get [textAlignmentProperty.native](): TextAlignment {
let textAlignmentGravity = this._nativeView.getGravity() & android.view.View.TEXT_ALIGNMENT_GRAVITY;
switch (textAlignmentGravity) {
case android.view.Gravity.LEFT:
return "left";
return TextAlignment.LEFT;
case android.view.Gravity.CENTER_HORIZONTAL:
return "center";
return TextAlignment.CENTER;
case android.view.Gravity.RIGHT:
return "right";
return TextAlignment.RIGHT;
default:
throw new Error("Invalid textGravity: " + textGravity);
throw new Error(`Unsupported android.view.View.TEXT_ALIGNMENT_GRAVITY: ${textAlignmentGravity}. Currently supported values are android.view.Gravity.LEFT, android.view.Gravity.CENTER_HORIZONTAL, and android.view.Gravity.RIGHT.`);
}
}
set [textAlignmentProperty.native](value: string) {
set [textAlignmentProperty.native](value: TextAlignment) {
let verticalGravity = this._nativeView.getGravity() & android.view.Gravity.VERTICAL_GRAVITY_MASK;
switch (value) {
case "left":
case TextAlignment.LEFT:
this._nativeView.setGravity(android.view.Gravity.LEFT | verticalGravity);
break;
case "center":
case TextAlignment.CENTER:
this._nativeView.setGravity(android.view.Gravity.CENTER_HORIZONTAL | verticalGravity);
break;
case "right":
case TextAlignment.RIGHT:
this._nativeView.setGravity(android.view.Gravity.RIGHT | verticalGravity);
break;
default:
break;
throw new Error(`Invalid text alignment value: ${value}. Valid values are: "${TextAlignment.LEFT}", "${TextAlignment.CENTER}", "${TextAlignment.RIGHT}".`);
}
}
//TextDecoration
get [textDecorationProperty.native](): TextDecoration {
return "none";
return TextDecoration.NONE;
}
set [textDecorationProperty.native](value: TextDecoration) {
let flags = 0;
let values = (value + "").split(" ");
let flags: number;
if (values.indexOf("underline") !== -1) {
flags = flags | android.graphics.Paint.UNDERLINE_TEXT_FLAG;
switch(value){
case TextDecoration.NONE:
flags = 0;
break;
case TextDecoration.UNDERLINE:
flags = android.graphics.Paint.UNDERLINE_TEXT_FLAG;
break;
case TextDecoration.LINE_THROUGH:
flags = android.graphics.Paint.STRIKE_THRU_TEXT_FLAG;
break;
case TextDecoration.UNDERLINE_LINE_THROUGH:
flags = android.graphics.Paint.UNDERLINE_TEXT_FLAG | android.graphics.Paint.STRIKE_THRU_TEXT_FLAG;
break;
default:
throw new Error(`Invalid text decoration value: ${value}. Valid values are: "${TextDecoration.NONE}", "${TextDecoration.UNDERLINE}", "${TextDecoration.LINE_THROUGH}", "${TextDecoration.UNDERLINE_LINE_THROUGH}".`);
}
if (values.indexOf("line-through") !== -1) {
flags = flags | android.graphics.Paint.STRIKE_THRU_TEXT_FLAG;
}
if (values.indexOf("none") === -1) {
this._nativeView.setPaintFlags(flags);
} else {
this._nativeView.setPaintFlags(0);
}
}
get [textTransformProperty.native](): "none" | "capitalize" | "uppercase" | "lowercase" {
return "none";
//TextTransform
get [textTransformProperty.native](): TextTransform {
return TextTransform.NONE;
}
set [textTransformProperty.native](value: "none" | "capitalize" | "uppercase" | "lowercase") {
set [textTransformProperty.native](value: TextTransform) {
this._setFormattedTextPropertyToNative(this.formattedText);
}
get [whiteSpaceProperty.native](): "normal" | "nowrap" {
return "normal";
private _originalTransformationMethod: android.text.method.TransformationMethod;
public _setFormattedTextPropertyToNative(value: FormattedString) {
// TODO: Check if there is an option to force call the transformation method without
// creating new native instance.
if (!this._nativeView) {
return;
}
set [whiteSpaceProperty.native](value: "normal" | "nowrap") {
if (!this._originalTransformationMethod) {
this._originalTransformationMethod = this.android.getTransformationMethod();
}
let newText = value ? value._formattedText : null;//newText is of type android.text.SpannableStringBuilder
if (newText) {
this._nativeView.setTransformationMethod(new TextTransformation(this.text, value, this.style.textTransform));
}
else {
if (this._originalTransformationMethod) {
this.android.setTransformationMethod(this._originalTransformationMethod);
this._originalTransformationMethod = null;
}
}
this._nativeView.setText(newText);
}
//WhiteSpace
get [whiteSpaceProperty.native](): WhiteSpace {
return WhiteSpace.NORMAL;
}
set [whiteSpaceProperty.native](value: WhiteSpace) {
let nativeView = this._nativeView;
let nowrap = value === "nowrap";
switch(value){
case WhiteSpace.NORMAL:
nativeView.setSingleLine(false);
nativeView.setEllipsize(null);
break;
case WhiteSpace.NO_WRAP:
nativeView.setSingleLine(true);
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.END);
break;
default:
throw new Error(`Invalid whitespace value: ${value}. Valid values are: "${WhiteSpace.NORMAL}", "${WhiteSpace.NO_WRAP}".`);
}
let nowrap = value === WhiteSpace.NO_WRAP;
nativeView.setSingleLine(nowrap);
nativeView.setEllipsize(nowrap ? android.text.TextUtils.TruncateAt.END : null);
}
@@ -209,3 +188,58 @@ export class TextBase extends TextBaseCommon {
org.nativescript.widgets.ViewHelper.setLetterspacing(this._nativeView, value);
}
}
@Interfaces([android.text.method.TransformationMethod])
class TextTransformation extends android.text.method.ReplacementTransformationMethod {
constructor(public originalText: string, public formattedText: FormattedString, public textTransform: TextTransform) {
super();
return global.__native(this);
}
protected getOriginal(): native.Array<string> {
return this.formattedText ? this.formattedText._formattedText : this.originalText;
}
protected getReplacement(): native.Array<string> {
let result: string = "";
let textTransform = this.textTransform
if (this.formattedText) {
for (let i = 0, length = this.formattedText.spans.length; i < length; i++) {
let span = this.formattedText.spans.getItem(i);
result += getTransformedText(span.text, textTransform);
// span.text = formatString(span.text, this.textTransform);
}
}
else {
result = getTransformedText(this.originalText, textTransform);
}
return result;
}
}
function getCapitalizedString(str: string): string {
let words = str.split(" ");
let newWords = [];
for (let i = 0, length = words.length; i < length; i++) {
let word = words[i].toLowerCase();
newWords.push(word.substr(0, 1).toUpperCase() + word.substring(1));
}
return newWords.join(" ");
}
export function getTransformedText(text: string, textTransform: TextTransform): string {
switch (textTransform) {
case TextTransform.NONE:
return text;
case TextTransform.UPPERCASE:
return text.toUpperCase();
case TextTransform.LOWERCASE:
return text.toLowerCase();
case TextTransform.CAPITALIZE:
return getCapitalizedString(text);
default:
throw new Error(`Invalid text transform value: ${textTransform}. Valid values are: "${TextTransform.NONE}", "${TextTransform.CAPITALIZE}", "${TextTransform.UPPERCASE}, "${TextTransform.LOWERCASE}".`);
}
}

View File

@@ -32,7 +32,7 @@
/**
* Gets or sets text-alignment style property.
*/
textAlignment: "left" | "center" | "right";
textAlignment: TextAlignment;
/**
* Gets or sets text decorations style property.
@@ -42,12 +42,12 @@
/**
* Gets or sets text transform style property.
*/
textTransform: "none" | "capitalize" | "uppercase" | "lowercase";
textTransform: TextTransform;
/**
* Gets or sets white space style property.
*/
whiteSpace: "normal" | "nowrap";
whiteSpace: WhiteSpace;
/**
* Called for every child element declared in xml.
@@ -57,9 +57,6 @@
*/
_addChildFromBuilder(name: string, value: any): void;
//@private
// _onTextPropertyChanged(value: string): void;
// _setFormattedTextPropertyToNative(value: any): void;
/**
* @private
* Called when the text property is changed to request layout.
@@ -68,6 +65,18 @@
//@endprivate
}
export const textProperty: Property<TextBase, string>;
export const formattedTextProperty: Property<TextBase, FormattedString>;
export type TextAlignment = "left" | "center" | "right";
export namespace TextAlignment {
export const LEFT: "left";
export const CENTER: "center";
export const RIGHT: "right";
export function isValid(value: any): boolean;
export function parse(value: string): TextAlignment;
}
export type TextDecoration = "none" | "underline" | "line-through" | "underline line-through";
export namespace TextDecoration {
export const NONE: "none";
@@ -79,15 +88,29 @@
}
export type TextTransform = "none" | "capitalize" | "uppercase" | "lowercase";
export namespace TextTransform {
export const NONE: "none";
export const CAPITALIZE: "capitalize";
export const UPPERCASE: "uppercase";
export const LOWERCASE: "lowercase";
export function isValid(value: any): boolean;
export function parse(value: string): TextTransform;
}
export function getTransformedText(text: string, transform: TextTransform): string;
export type WhiteSpace = "normal" | "nowrap";
export namespace WhiteSpace {
export const NORMAL: "normal";
export const NO_WRAP: "nowrap";
export function isValid(value: any): boolean;
export function parse(value: string): WhiteSpace;
}
export const textProperty: Property<TextBase, string>;
export const formattedTextProperty: Property<TextBase, FormattedString>;
export const textAlignmentProperty: InheritedCssProperty<Style, "left" | "center" | "right">;
export const textAlignmentProperty: InheritedCssProperty<Style, TextAlignment>;
export const textDecorationProperty: CssProperty<Style, TextDecoration>;
export const textTransformProperty: CssProperty<Style, TextTransform>;
export const whiteSpaceProperty: CssProperty<Style, "normal" | "nowrap">;
export const whiteSpaceProperty: CssProperty<Style, WhiteSpace>;
export const letterSpacingProperty: CssProperty<Style, number>;
//Used by tab view
export function getTransformedText(text: string, textTransform: TextTransform): string;
}

View File

@@ -1,155 +1,15 @@
import {
TextBaseCommon, textProperty, formattedTextProperty, textAlignmentProperty, textDecorationProperty,
textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty, Font, Color, FormattedString,
TextDecoration
TextDecoration, TextAlignment, TextTransform
} from "./text-base-common";
export * from "./text-base-common";
function NSStringFromNSAttributedString(source: NSAttributedString | string): NSString {
return NSString.stringWithString(source instanceof NSAttributedString && source.string || <string>source);
}
export function getTransformedText(text: string, transform: "none" | "capitalize" | "uppercase" | "lowercase"): string {
switch (transform) {
case "uppercase":
return NSStringFromNSAttributedString(text).uppercaseString;
case "lowercase":
return NSStringFromNSAttributedString(text).lowercaseString;
case "capitalize":
return NSStringFromNSAttributedString(text).capitalizedString;
case "none":
default:
return text;
}
}
function updateFormattedStringTextDecoration(formattedText: FormattedString, decoration: string, ): void {
// TODO: Refactor this method so it doesn't modify FormattedString properties.
// Instead it should create NSAttributedString and apply it to the nativeView.
let textDecoration = decoration + "";
if (textDecoration.indexOf("none") !== -1) {
formattedText.underline = NSUnderlineStyle.StyleNone;
formattedText.strikethrough = NSUnderlineStyle.StyleNone;
}
else {
if (textDecoration.indexOf("underline") !== -1) {
formattedText.underline = NSUnderlineStyle.StyleSingle;
} else {
formattedText.underline = NSUnderlineStyle.StyleNone;
}
if (textDecoration.indexOf("line-through") !== -1) {
formattedText.strikethrough = NSUnderlineStyle.StyleSingle;
} else {
formattedText.strikethrough = NSUnderlineStyle.StyleNone;
}
}
}
function updateFormattedStringTextTransformation(formattedText: FormattedString, transform: "none" | "capitalize" | "uppercase" | "lowercase"): 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, transform);
}
}
function setFormattedTextDecorationAndTransform(formattedText: FormattedString, nativeView: UITextField | UITextView | UILabel | UIButton, decoration: string, transform: "none" | "capitalize" | "uppercase" | "lowercase", letterSpacing: number) {
updateFormattedStringTextDecoration(formattedText, decoration);
updateFormattedStringTextTransformation(formattedText, transform);
if (typeof letterSpacing === "number" && !isNaN(letterSpacing)) {
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;
}
}
}
function setTextDecorationAndTransform(text: string, nativeView: UITextField | UITextView | UILabel | UIButton, decoration: string, transform: "none" | "capitalize" | "uppercase" | "lowercase", letterSpacing: number, color: Color) {
let hasLetterSpacing = typeof letterSpacing === "number" && !isNaN(letterSpacing);
let decorationValues = decoration + "";
let dict = new Map<string, number>();
if (decorationValues.indexOf("none") === -1) {
if (decorationValues.indexOf("underline") !== -1) {
dict.set(NSUnderlineStyleAttributeName, NSUnderlineStyle.StyleSingle);
}
if (decorationValues.indexOf("line-through") !== -1) {
dict.set(NSStrikethroughStyleAttributeName, NSUnderlineStyle.StyleSingle);
}
}
if (hasLetterSpacing) {
dict.set(NSKernAttributeName, letterSpacing * nativeView.font.pointSize);
}
if (color) {
dict.set(NSForegroundColorAttributeName, color.ios);
}
let source = getTransformedText(text, transform);
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;
}
}
}
export class TextBase extends TextBaseCommon {
public nativeView: UITextField | UITextView | UILabel | UIButton;
// public _onTextPropertyChanged(value: string) {
// var newValue = toUIString(value);
// this.ios.text = newValue;
// //RemoveThisDoubleCall
// // this.style._updateTextDecoration();
// // this.style._updateTextTransform();
// this._requestLayoutOnTextChanged();
// }
public _setFormattedTextPropertyToNative(value: FormattedString) {
let newText = value ? value._formattedText : null;
let nativeView = this.nativeView;
if (nativeView instanceof UIButton) {
nativeView.setAttributedTitleForState(newText, UIControlState.Normal);
} else {
nativeView.attributedText = newText;
}
//RemoveThisDoubleCall
// this.style._updateTextDecoration();
// this.style._updateTextTransform();
}
//Text
get [textProperty.native](): string {
let nativeView = this.nativeView;
if (nativeView instanceof UIButton) {
@@ -176,6 +36,7 @@ export class TextBase extends TextBaseCommon {
this._requestLayoutOnTextChanged();
}
//FormattedText
get [formattedTextProperty.native](): FormattedString {
return null;
}
@@ -183,6 +44,17 @@ export class TextBase extends TextBaseCommon {
this._setFormattedTextPropertyToNative(value);
}
public _setFormattedTextPropertyToNative(value: FormattedString) {
let newText = value ? value._formattedText : null;
let nativeView = this.nativeView;
if (nativeView instanceof UIButton) {
nativeView.setAttributedTitleForState(newText, UIControlState.Normal);
} else {
nativeView.attributedText = newText;
}
}
//Color
get [colorProperty.native](): UIColor {
let nativeView = this.nativeView;
if (nativeView instanceof UIButton) {
@@ -200,6 +72,7 @@ export class TextBase extends TextBaseCommon {
}
}
//FontInternal
get [fontInternalProperty.native](): UIFont {
let nativeView = this.nativeView;
nativeView = nativeView instanceof UIButton ? nativeView.titleLabel : nativeView;
@@ -212,41 +85,43 @@ export class TextBase extends TextBaseCommon {
nativeView.font = font;
}
get [textAlignmentProperty.native](): string {
//TextAlignment
get [textAlignmentProperty.native](): TextAlignment {
let nativeView = this.nativeView;
nativeView = nativeView instanceof UIButton ? nativeView.titleLabel : nativeView;
switch (nativeView.textAlignment) {
case NSTextAlignment.Left:
return "left";
return TextAlignment.LEFT;
case NSTextAlignment.Center:
return "center";
return TextAlignment.CENTER;
case NSTextAlignment.Right:
return "right";
return TextAlignment.RIGHT;
default:
throw new Error(`Unsupported NSTextAlignment: ${nativeView.textAlignment}. Currently supported values are NSTextAlignment.Left, NSTextAlignment.Center, and NSTextAlignment.Right.`);
}
}
set [textAlignmentProperty.native](value: string) {
set [textAlignmentProperty.native](value: TextAlignment) {
let nativeView = this.nativeView;
nativeView = nativeView instanceof UIButton ? nativeView.titleLabel : nativeView;
// NOTE: if Button textAlignment is not enough - set also btn.contentHorizontalAlignment
switch (value) {
case "left":
case TextAlignment.LEFT:
nativeView.textAlignment = NSTextAlignment.Left;
break;
case "center":
case TextAlignment.CENTER:
nativeView.textAlignment = NSTextAlignment.Center;
break;
case "right":
case TextAlignment.RIGHT:
nativeView.textAlignment = NSTextAlignment.Right;
break;
default:
break;
throw new Error(`Invalid text alignment value: ${value}. Valid values are: "${TextAlignment.LEFT}", "${TextAlignment.CENTER}", "${TextAlignment.RIGHT}".`);
}
}
//TextDecoration
get [textDecorationProperty.native](): TextDecoration {
return "none";
return TextDecoration.NONE;
}
set [textDecorationProperty.native](value: TextDecoration) {
if (this.formattedText) {
@@ -256,10 +131,11 @@ export class TextBase extends TextBaseCommon {
}
}
get [textTransformProperty.native](): string {
return "none";
//TextTransform
get [textTransformProperty.native](): TextTransform {
return TextTransform.NONE;
}
set [textTransformProperty.native](value: "none" | "capitalize" | "uppercase" | "lowercase") {
set [textTransformProperty.native](value: TextTransform) {
if (this.formattedText) {
setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, this.style.textDecoration, value, this.style.letterSpacing);
} else {
@@ -267,21 +143,7 @@ export class TextBase extends TextBaseCommon {
}
}
// get [whiteSpaceProperty.native](): string {
// return WhiteSpace.normal;
// }
// set [whiteSpaceProperty.native](value: string) {
// let nativeView = this.nativeView;
// if (value === WhiteSpace.normal) {
// nativeView.lineBreakMode = NSLineBreakMode.ByWordWrapping;
// nativeView.numberOfLines = 0;
// }
// else {
// nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
// nativeView.numberOfLines = 1;
// }
// }
// LetterSpacing
get [letterSpacingProperty.native](): number {
return Number.NaN;
}
@@ -292,20 +154,126 @@ export class TextBase extends TextBaseCommon {
setTextDecorationAndTransform(this.text, this.nativeView, this.style.textDecoration, this.style.textTransform, value, this.style.color);
}
}
// private _settingFormattedTextPropertyToNative = false;
// public _onStylePropertyChanged(property: dependencyObservable.Property): void {
// if (this._settingFormattedTextPropertyToNative) {
// // Guard against stack-overflow.
// return;
// }
// if (this.formattedText) {
// // Re-apply the formatted text to override style changes if needed.
// // https://github.com/NativeScript/NativeScript/issues/1078
// this._settingFormattedTextPropertyToNative = true;
// this._setFormattedTextPropertyToNative(this.formattedText);
// this._settingFormattedTextPropertyToNative = false;
// }
// }
}
export function getTransformedText(text: string, textTransform: TextTransform): string {
switch (textTransform) {
case TextTransform.NONE:
return text;
case TextTransform.UPPERCASE:
return NSStringFromNSAttributedString(text).uppercaseString;
case TextTransform.LOWERCASE:
return NSStringFromNSAttributedString(text).lowercaseString;
case TextTransform.CAPITALIZE:
return NSStringFromNSAttributedString(text).capitalizedString;
default:
throw new Error(`Invalid text transform value: ${textTransform}. Valid values are: "${TextTransform.NONE}", "${TextTransform.CAPITALIZE}", "${TextTransform.UPPERCASE}, "${TextTransform.LOWERCASE}".`);
}
}
function NSStringFromNSAttributedString(source: NSAttributedString | string): NSString {
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);
if (typeof letterSpacing === "number" && !isNaN(letterSpacing)) {
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;
}
}
}
function setTextDecorationAndTransform(text: string, nativeView: UITextField | UITextView | UILabel | UIButton, textDecoration: TextDecoration, textTransform: TextTransform, letterSpacing: number, color: Color) {
let hasLetterSpacing = typeof letterSpacing === "number" && !isNaN(letterSpacing);
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 (hasLetterSpacing) {
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;
}
}
}

View File

@@ -5,95 +5,6 @@ export * from "./utils-common";
// We are using "ad" here to avoid namespace collision with the global android object
export module ad {
export function setTextDecoration(view: android.widget.TextView, value: string) {
var flags = 0;
var values = (value + "").split(" ");
if (values.indexOf("underline") !== -1) {
flags = flags | android.graphics.Paint.UNDERLINE_TEXT_FLAG;
}
if (values.indexOf("line-through") !== -1) {
flags = flags | android.graphics.Paint.STRIKE_THRU_TEXT_FLAG;
}
if (values.indexOf("none") === -1) {
view.setPaintFlags(flags);
} else {
view.setPaintFlags(0);
}
}
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);
}
}
export function getTransformedString(textTransform: string, view, stringToTransform: string): string {
let result: string;
switch (textTransform) {
case "uppercase":
view.setTransformationMethod(null);
result = stringToTransform.toUpperCase();
break;
case "lowercase":
view.setTransformationMethod(null);
result = stringToTransform.toLowerCase();
break;
case "capitalize":
view.setTransformationMethod(null);
result = getCapitalizedString(stringToTransform);
break;
case "none":
default:
result = view["originalString"] || stringToTransform;
if (view["transformationMethod"]) {
view.setTransformationMethod(view["transformationMethod"]);
}
break;
}
if (!view["originalString"]) {
view["originalString"] = stringToTransform;
view["transformationMethod"] = view.getTransformationMethod();
}
return result;
}
function getCapitalizedString(str: string): string {
var words = str.split(" ");
var newWords = [];
for (let i = 0; i < words.length; i++) {
let word = words[i].toLowerCase();
newWords.push(word.substr(0, 1).toUpperCase() + word.substring(1));
}
return newWords.join(" ");
}
export function setWhiteSpace(view: android.widget.TextView, value: string) {
let nowrap = value === "nowrap";
view.setSingleLine(nowrap);
view.setEllipsize(nowrap ? android.text.TextUtils.TruncateAt.END : null);
}
let nativeApp: android.app.Application;
declare var com;
export function getApplication() {

View File

@@ -78,11 +78,6 @@
* Module with android specific utilities.
*/
module ad {
export function setTextTransform(view, value: string);
export function setWhiteSpace(view, value: string);
export function setTextDecoration(view, value: string);
export function getTransformedString(textTransform: string, view, stringToTransform: string): string;
/**
* Gets the native Android application instance.
*/
@@ -163,9 +158,6 @@
* Example: getter(NSRunLoop, NSRunLoop.currentRunLoop).runUntilDate(NSDate.dateWithTimeIntervalSinceNow(waitTime));
*/
export function getter<T>(_this: any, propertyValue: T | {(): T}): T;
export function getTransformedText(view, source: string, transform: string): string;
export function setWhiteSpace(view, value: string, parentView?: any);
export function setTextAlignment(view, value: string);
// Common properties between UILabel, UITextView and UITextField
export interface TextUIView {

View File

@@ -34,22 +34,6 @@ export module layout {
}
export module ios {
export function setTextAlignment(view: dts.ios.TextUIView, value: string) {
switch (value) {
case "left":
view.textAlignment = NSTextAlignment.Left;
break;
case "center":
view.textAlignment = NSTextAlignment.Center;
break;
case "right":
view.textAlignment = NSTextAlignment.Right;
break;
default:
break;
}
}
export function getter<T>(_this: any, property: T | { (): T }): T {
if (typeof property === "function") {
return (<{ (): T }>property).call(_this);
@@ -58,50 +42,6 @@ export module ios {
}
}
export function getTransformedText(view, source: string, transform: string): string {
let result = source;
switch (transform) {
case "uppercase":
result = NSStringFromNSAttributedString(source).uppercaseString;
break;
case "lowercase":
result = NSStringFromNSAttributedString(source).lowercaseString;
break;
case "capitalize":
result = NSStringFromNSAttributedString(source).capitalizedString;
break;
case "none":
default:
result = view.text;
break;
}
return result;
}
function NSStringFromNSAttributedString(source: NSAttributedString | string): NSString {
return NSString.stringWithString(source instanceof NSAttributedString && source.string || <string>source);
}
export function setWhiteSpace(view: dts.ios.TextUIView, value: string, parentView?: UIView) {
if (value === "normal") {
view.lineBreakMode = NSLineBreakMode.ByWordWrapping;
view.numberOfLines = 0;
}
else {
if (parentView) {
view.lineBreakMode = NSLineBreakMode.ByTruncatingMiddle;
} else {
view.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
}
view.numberOfLines = 1;
}
}
export module collections {
export function jsArrayToNSArray(str: string[]): NSArray<any> {
return NSArray.arrayWithArray(<any>str);