Merge pull request #1046 from NativeScript/text-decoration

text-decoration implemented
This commit is contained in:
Vladimir Enchev
2015-11-09 09:17:04 +02:00
16 changed files with 229 additions and 4 deletions

View File

@ -238,6 +238,7 @@
<TypeScriptCompile Include="apps\ui-tests-app\action-bar\color.ts">
<DependentUpon>color.xml</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="apps\ui-tests-app\css\text-decoration.ts" />
<TypeScriptCompile Include="apps\ui-tests-app\html-view\html-view.ts">
<DependentUpon>html-view.xml</DependentUpon>
</TypeScriptCompile>

View File

@ -19,4 +19,9 @@ ActionBar, TabView, ActivityIndicator, Label, Button, TextView, TextField, Searc
Switch, Progress, Slider, SegmentedBar {
color: mediumaquamarine;
background-color: aquamarine;
}*/
/*
TextView, TextField, Label, Button {
text-decoration: underline;
}*/

View File

@ -0,0 +1,17 @@
var obj;
export function loaded(args) {
obj = args.object;
}
export function butonTap(args) {
if (obj.style.textDecoration === "underline") {
obj.style.textDecoration = "line-through";
} else if (obj.style.textDecoration === "line-through") {
obj.style.textDecoration = "line-through underline";
} else if (obj.style.textDecoration === "line-through underline") {
obj.style.textDecoration = "none";
} else if (obj.style.textDecoration === "none") {
obj.style.textDecoration = "underline";
}
}

View File

@ -0,0 +1,32 @@
<Page >
<ScrollView>
<StackLayout>
<Button text="Change" tap="butonTap" />
<Label text="Text" style.textDecoration="underline" loaded="loaded"/>
<Label text="Label" style="text-decoration:none" />
<Label text="Label" style="text-decoration:underline" />
<Label text="Label" style="text-decoration:line-through" />
<Label text="Label" style="text-decoration:line-through underline" />
<Label text="Label" style="text-decoration:line-through underline none" />
<TextField text="TextField" style="text-decoration:none" />
<TextField text="TextField" style="text-decoration:underline" />
<TextField text="TextField" style="text-decoration:line-through" />
<TextField text="TextField" style="text-decoration:underline line-through" />
<TextField text="TextField" style="text-decoration:underline line-through none" />
<TextView text="TextView" style="text-decoration:none" />
<TextView text="TextView" style="text-decoration:underline" />
<TextView text="TextView" style="text-decoration:line-through" />
<TextView text="TextView" style="text-decoration:line-through underline" />
<TextView text="TextView" style="text-decoration:line-through underline none" />
<Button text="Button" style="text-decoration:none" />
<Button text="Button" style="text-decoration:underline" />
<Button text="Button" style="text-decoration:line-through" />
<Button text="Button" style="text-decoration:underline line-through" />
<Button text="Button" style="text-decoration:underline line-through none" />
</StackLayout>
</ScrollView>
</Page>

View File

@ -90,4 +90,5 @@ examples.set("textfield", "text-field/text-field");
examples.set("webview", "web-view/web-view");
examples.set("webtest", "web-view/web-vew-test");
examples.set("decoration", "css/text-decoration");
//VM.set("selected", "tabAll");

21
ui/enums/enums.d.ts vendored
View File

@ -417,7 +417,26 @@
*/
export var italic: string;
}
/**
* Specifies different text decorations.
*/
export module TextDecoration {
/**
* No decoration.
*/
export var none: string;
/**
* Text decoration underline.
*/
export var underline: string;
/**
* Text decoration line-through.
*/
export var lineThrough: string;
}
/**
* Specifies different font weights.

View File

@ -20,6 +20,12 @@ export module TextAlignment {
export var right = "right";
}
export module TextDecoration {
export var none = "none";
export var underline = "underline";
export var lineThrough = "line-through";
}
export module Orientation {
export var horizontal = "horizontal";
export var vertical = "vertical";

View File

@ -17,10 +17,18 @@ export function textAlignConverter(value: string): string {
case enums.TextAlignment.center:
case enums.TextAlignment.right:
return value;
break;
default:
throw new Error("CSS text-align \"" + value + "\" is not supported.");
break;
}
}
export function textDecorationConverter(value: string): string {
var values = (value + "").split(" ");
if (values.indexOf(enums.TextDecoration.none) !== -1 || values.indexOf(enums.TextDecoration.underline) !== -1 || values.indexOf(enums.TextDecoration.lineThrough) !== -1) {
return value;
} else {
throw new Error("CSS text-decoration \"" + value + "\" is not supported.");
}
}

View File

@ -44,6 +44,7 @@ declare module "ui/styling/style" {
public fontWeight: string;
public font: string;
public textAlignment: string;
public textDecoration: string;
public minWidth: number;
public minHeight: number;
public width: number;
@ -72,6 +73,7 @@ declare module "ui/styling/style" {
public _inheritStyleProperty(property: Property): void;
public _inheritStyleProperties(): void;
public _boundsChanged(): void;
public _updateTextDecoration(): void;
}
export function registerHandler(property: Property, handler: styling.stylers.StylePropertyChangedHandler, className?: string);

View File

@ -239,6 +239,12 @@ function isVisibilityValid(value: string): boolean {
return value === enums.Visibility.visible || value === enums.Visibility.collapse || value === enums.Visibility.collapsed;
}
function isTextDecorationValid(value: string): boolean {
var values = (value + "").split(" ");
return values.indexOf(enums.TextDecoration.none) !== -1 || values.indexOf(enums.TextDecoration.underline) !== -1 || values.indexOf(enums.TextDecoration.lineThrough) !== -1;
}
function onVisibilityChanged(data: PropertyChangeData) {
(<any>data.object)._view._isVisibleCache = data.newValue === enums.Visibility.visible;
}
@ -536,6 +542,19 @@ export class Style extends DependencyObservable implements styling.Style {
this._setValue(opacityProperty, value);
}
get textDecoration(): string {
return this._getValue(textDecorationProperty);
}
set textDecoration(value: string) {
this._setValue(textDecorationProperty, value);
}
public _updateTextDecoration() {
if (this._getValue(textDecorationProperty) !== enums.TextDecoration.none) {
this._applyProperty(textDecorationProperty, this._getValue(textDecorationProperty));
}
}
constructor(parentView: View) {
super();
this._view = parentView;
@ -788,6 +807,9 @@ export var visibilityProperty = new styleProperty.Property("visibility", "visibi
export var opacityProperty = new styleProperty.Property("opacity", "opacity",
new PropertyMetadata(1.0, PropertyMetadataSettings.None, undefined, isOpacityValid), converters.opacityConverter);
export var textDecorationProperty = new styleProperty.Property("textDecoration", "text-decoration",
new PropertyMetadata(enums.TextDecoration.none, PropertyMetadataSettings.None, undefined, isTextDecorationValid), converters.textDecorationConverter);
// Helper property holding most layout related properties available in CSS.
// When layout related properties are set in CSS we chache them and send them to the native view in a single call.
export var nativeLayoutParamsProperty = new styleProperty.Property("nativeLayoutParams", "nativeLayoutParams",

View File

@ -416,6 +416,15 @@ export class TextViewStyler implements definition.stylers.Styler {
return view._nativeView.getGravity();
}
// text-decoration
private static setTextDecorationProperty(view: view.View, newValue: any) {
setTextDecoration(view._nativeView, newValue);
}
private static resetTextDecorationProperty(view: view.View, nativeValue: any) {
setTextDecoration(view._nativeView, enums.TextDecoration.none);
}
public static registerHandlers() {
style.registerHandler(style.colorProperty, new stylersCommon.StylePropertyChangedHandler(
TextViewStyler.setColorProperty,
@ -432,6 +441,10 @@ export class TextViewStyler implements definition.stylers.Styler {
TextViewStyler.resetTextAlignmentProperty,
TextViewStyler.getNativeTextAlignmentValue), "TextBase");
style.registerHandler(style.textDecorationProperty, new stylersCommon.StylePropertyChangedHandler(
TextViewStyler.setTextDecorationProperty,
TextViewStyler.resetTextDecorationProperty), "TextBase");
// Register the same stylers for Button.
// It also derives from TextView but is not under TextBase in our View hierarchy.
style.registerHandler(style.colorProperty, new stylersCommon.StylePropertyChangedHandler(
@ -448,9 +461,33 @@ export class TextViewStyler implements definition.stylers.Styler {
TextViewStyler.setTextAlignmentProperty,
TextViewStyler.resetTextAlignmentProperty,
TextViewStyler.getNativeTextAlignmentValue), "Button");
style.registerHandler(style.textDecorationProperty, new stylersCommon.StylePropertyChangedHandler(
TextViewStyler.setTextDecorationProperty,
TextViewStyler.resetTextDecorationProperty), "Button");
}
}
function setTextDecoration(view: android.widget.TextView, value: string) {
var flags = 0;
var values = (value + "").split(" ");
if (values.indexOf(enums.TextDecoration.underline) !== -1) {
flags = flags | android.graphics.Paint.UNDERLINE_TEXT_FLAG;
}
if (values.indexOf(enums.TextDecoration.lineThrough) !== -1) {
flags = flags | android.graphics.Paint.STRIKE_THRU_TEXT_FLAG;
}
if (values.indexOf(enums.TextDecoration.none) === -1) {
view.setPaintFlags(flags);
} else {
view.setPaintFlags(0);
}
}
export class ActivityIndicatorStyler implements definition.stylers.Styler {
private static setColorProperty(view: view.View, newValue: any) {
var bar = <android.widget.ProgressBar>view._nativeView;
@ -823,7 +860,7 @@ export class ActionBarStyler implements definition.stylers.Styler {
private static setColorProperty(view: view.View, newValue: any) {
var toolbar = (<android.support.v7.widget.Toolbar>view._nativeView);
toolbar.setTitleTextColor(newValue);
}
private static resetColorProperty(view: view.View, nativeValue: any) {

View File

@ -7,6 +7,7 @@ import font = require("ui/styling/font");
import background = require("ui/styling/background");
import frame = require("ui/frame");
import tabView = require("ui/tab-view");
import formattedString = require("text/formatted-string");
global.moduleMerge(stylersCommon, exports);
@ -14,6 +15,8 @@ interface TextUIView {
font: UIFont;
textAlignment: number;
textColor: UIColor;
text : string;
attributedText : NSAttributedString;
}
var ignorePropertyHandler = new stylersCommon.StylePropertyChangedHandler(
@ -251,6 +254,15 @@ export class ButtonStyler implements definition.stylers.Styler {
(<UIButton>view._nativeView).contentEdgeInsets = UIEdgeInsetsFromString("{0,0,0,0}");
}
// text-decoration
private static setTextDecorationProperty(view: view.View, newValue: any) {
setTextDecoration((<UIButton>view.ios).titleLabel, newValue);
}
private static resetTextDecorationProperty(view: view.View, nativeValue: any) {
setTextDecoration((<UIButton>view.ios).titleLabel, enums.TextDecoration.none);
}
public static registerHandlers() {
style.registerHandler(style.colorProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setColorProperty,
@ -270,6 +282,10 @@ export class ButtonStyler implements definition.stylers.Styler {
style.registerHandler(style.nativePaddingsProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setPaddingProperty,
ButtonStyler.resetPaddingProperty), "Button");
style.registerHandler(style.textDecorationProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setTextDecorationProperty,
ButtonStyler.resetTextDecorationProperty), "Button");
}
}
@ -305,6 +321,15 @@ export class TextBaseStyler implements definition.stylers.Styler {
return ios.textAlignment;
}
// text-decoration
private static setTextDecorationProperty(view: view.View, newValue: any) {
setTextDecoration(view._nativeView, newValue);
}
private static resetTextDecorationProperty(view: view.View, nativeValue: any) {
setTextDecoration(view._nativeView, enums.TextDecoration.none);
}
// color
private static setColorProperty(view: view.View, newValue: any) {
var ios: TextUIView = <TextUIView>view._nativeView;
@ -336,6 +361,10 @@ export class TextBaseStyler implements definition.stylers.Styler {
TextBaseStyler.setColorProperty,
TextBaseStyler.resetColorProperty,
TextBaseStyler.getNativeColorValue), "TextBase");
style.registerHandler(style.textDecorationProperty, new stylersCommon.StylePropertyChangedHandler(
TextBaseStyler.setTextDecorationProperty,
TextBaseStyler.resetTextDecorationProperty), "TextBase");
}
}
@ -880,6 +909,36 @@ function setTextAlignment(view: TextUIView, value: string) {
}
}
function setTextDecoration(view: TextUIView, value: string) {
var attributes: NSMutableDictionary = NSMutableDictionary.alloc().init();
var values = (value + "").split(" ");
if (values.indexOf(enums.TextDecoration.underline) !== -1) {
attributes.setObjectForKey(NSUnderlineStyle.NSUnderlineStyleSingle, NSUnderlineStyleAttributeName);
}
if (values.indexOf(enums.TextDecoration.lineThrough) !== -1) {
attributes.setObjectForKey(NSUnderlineStyle.NSUnderlineStyleSingle, NSStrikethroughStyleAttributeName);
}
if (values.indexOf(enums.TextDecoration.none) === -1) {
setTextDecorationNative(view, view.text || view.attributedText, attributes);
} else {
setTextDecorationNative(view, view.text || view.attributedText, NSMutableDictionary.alloc().init());
}
}
function setTextDecorationNative(view: 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 {
view.attributedText = NSAttributedString.alloc().initWithStringAttributes(<string>value, attributes);
}
}
// Register all styler at the end.
export function _registerDefaultStylers() {
style.registerNoStylingClass("Frame");

View File

@ -205,6 +205,7 @@
public _syncNativeProperties(): void;
public _inheritStyleProperty(property: dependencyObservable.Property): void;
public _inheritStyleProperties(): void;
public _updateTextDecoration(): void;
//@endprivate
}

View File

@ -95,6 +95,7 @@ export class TextBase extends view.View implements definition.TextBase, formatte
}
else if (this.ios) {
this.ios.text = data.newValue + "";
this.style._updateTextDecoration();
}
}
@ -103,6 +104,7 @@ export class TextBase extends view.View implements definition.TextBase, formatte
this.android.setText(value._formattedText);
} else if (this.ios) {
this.ios.attributedText = value._formattedText;
this.style._updateTextDecoration();
this.requestLayout();
}
}

View File

@ -69,6 +69,11 @@ class UITextFieldDelegateImpl extends NSObject implements UITextFieldDelegate {
public textFieldShouldChangeCharactersInRangeReplacementString(textField: UITextField, range: NSRange, replacementString: string): boolean {
let owner = this._owner.get();
if (owner) {
var r = textField.selectedTextRange;
owner.style._updateTextDecoration();
textField.selectedTextRange = r;
if (owner.updateTextTrigger === enums.UpdateTextTrigger.textChanged) {
if (textField.secureTextEntry && this.firstEdit) {
owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, replacementString);

View File

@ -24,6 +24,10 @@ class UITextViewDelegateImpl extends NSObject implements UITextViewDelegate {
return true;
}
public textViewDidBeginEditing(textView: UITextView) {
this._owner.style._updateTextDecoration();
}
public textViewDidEndEditing(textView: UITextView) {
if (this._owner.updateTextTrigger === enums.UpdateTextTrigger.focusLost) {
this._owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, textView.text);
@ -34,6 +38,10 @@ class UITextViewDelegateImpl extends NSObject implements UITextViewDelegate {
}
public textViewDidChange(textView: UITextView) {
var range = textView.selectedRange;
this._owner.style._updateTextDecoration();
textView.selectedRange = range;
if (this._owner.updateTextTrigger === enums.UpdateTextTrigger.textChanged) {
this._owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, textView.text);
}