From 45394f9672724caab8b8e58e5f0236f7b7786c2f Mon Sep 17 00:00:00 2001 From: Vladimir Enchev Date: Thu, 5 Nov 2015 16:00:10 +0200 Subject: [PATCH] initial commit --- apps/gallery-app/app.css | 6 ++++- ui/enums/enums.d.ts | 25 ++++++++++++++++++ ui/enums/enums.ts | 7 +++++ ui/styling/converters.ts | 14 ++++++++++ ui/styling/style.d.ts | 2 ++ ui/styling/style.ts | 20 ++++++++++++++ ui/styling/stylers.ios.ts | 46 +++++++++++++++++++++++++++++++++ ui/styling/styling.d.ts | 1 + ui/text-base/text-base.ts | 2 ++ ui/text-field/text-field.ios.ts | 3 +++ ui/text-view/text-view.ios.ts | 4 +++ 11 files changed, 129 insertions(+), 1 deletion(-) diff --git a/apps/gallery-app/app.css b/apps/gallery-app/app.css index 0dc6af8bc..569d88605 100644 --- a/apps/gallery-app/app.css +++ b/apps/gallery-app/app.css @@ -19,4 +19,8 @@ ActionBar, TabView, ActivityIndicator, Label, Button, TextView, TextField, Searc Switch, Progress, Slider, SegmentedBar { color: mediumaquamarine; background-color: aquamarine; -}*/ \ No newline at end of file +}*/ + +TextView, TextField, Label, Button { + text-decoration: underline; +} \ No newline at end of file diff --git a/ui/enums/enums.d.ts b/ui/enums/enums.d.ts index 997b6c8b6..2eada7b88 100644 --- a/ui/enums/enums.d.ts +++ b/ui/enums/enums.d.ts @@ -417,6 +417,31 @@ */ 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 overline. + */ + export var overline: string; + + /** + * Text decoration line-through. + */ + export var lineThrough: string; + } /** diff --git a/ui/enums/enums.ts b/ui/enums/enums.ts index f5b98857a..3b2a409a0 100644 --- a/ui/enums/enums.ts +++ b/ui/enums/enums.ts @@ -20,6 +20,13 @@ export module TextAlignment { export var right = "right"; } +export module TextDecoration { + export var none = "none"; + export var underline = "underline"; + export var overline = "overline"; + export var lineThrough = "lineThrough"; +} + export module Orientation { export var horizontal = "horizontal"; export var vertical = "vertical"; diff --git a/ui/styling/converters.ts b/ui/styling/converters.ts index e81928872..a74f806a8 100644 --- a/ui/styling/converters.ts +++ b/ui/styling/converters.ts @@ -24,6 +24,20 @@ export function textAlignConverter(value: string): string { } } +export function textDecorationConverter(value: string): string { + switch (value) { + case enums.TextDecoration.none: + case enums.TextDecoration.overline: + case enums.TextDecoration.underline: + case enums.TextDecoration.lineThrough: + return value; + break; + default: + throw new Error("CSS text-decoration \"" + value + "\" is not supported."); + break; + } +} + export var numberConverter = parseFloat; export function visibilityConverter(value: string): string { diff --git a/ui/styling/style.d.ts b/ui/styling/style.d.ts index 256cabe7e..a3790cbaf 100644 --- a/ui/styling/style.d.ts +++ b/ui/styling/style.d.ts @@ -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); diff --git a/ui/styling/style.ts b/ui/styling/style.ts index 1ebe2aba2..a43984e1f 100644 --- a/ui/styling/style.ts +++ b/ui/styling/style.ts @@ -239,6 +239,10 @@ function isVisibilityValid(value: string): boolean { return value === enums.Visibility.visible || value === enums.Visibility.collapse || value === enums.Visibility.collapsed; } +function isTextDecorationValid(value: string): boolean { + return value === enums.TextDecoration.none || value === enums.TextDecoration.overline || value === enums.TextDecoration.underline || value === enums.TextDecoration.lineThrough; +} + function onVisibilityChanged(data: PropertyChangeData) { (data.object)._view._isVisibleCache = data.newValue === enums.Visibility.visible; } @@ -536,6 +540,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 +805,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", diff --git a/ui/styling/stylers.ios.ts b/ui/styling/stylers.ios.ts index 25e690d9e..205914e4b 100644 --- a/ui/styling/stylers.ios.ts +++ b/ui/styling/stylers.ios.ts @@ -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( @@ -305,6 +308,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 = view._nativeView; @@ -336,6 +348,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 +896,36 @@ function setTextAlignment(view: TextUIView, value: string) { } } +function setTextDecoration(view: TextUIView, value: string) { + switch (value) { + case enums.TextDecoration.none: + + break; + case enums.TextDecoration.overline: + + break; + case enums.TextDecoration.underline: + setTextDecorationNative(view, view.text || view.attributedText, NSUnderlineStyleAttributeName); + break; + case enums.TextDecoration.lineThrough: + setTextDecorationNative(view, view.text || view.attributedText, NSStrikethroughStyleAttributeName); + break; + default: + break; + } +} + +function setTextDecorationNative(view: TextUIView, value: string | NSAttributedString, attribute: string) { + var attributedString: NSMutableAttributedString; + + if (value instanceof NSAttributedString) { + attributedString = NSMutableAttributedString.alloc().initWithAttributedString(value); + attributedString.addAttributesRange({ [attribute]: NSUnderlineStyle.NSUnderlineStyleSingle }, NSRangeFromString(attributedString.string)); + } else { + view.attributedText = NSAttributedString.alloc().initWithStringAttributes(value, { [attribute]: NSUnderlineStyle.NSUnderlineStyleSingle }); + } +} + // Register all styler at the end. export function _registerDefaultStylers() { style.registerNoStylingClass("Frame"); diff --git a/ui/styling/styling.d.ts b/ui/styling/styling.d.ts index ede2671a4..033854dc2 100644 --- a/ui/styling/styling.d.ts +++ b/ui/styling/styling.d.ts @@ -205,6 +205,7 @@ public _syncNativeProperties(): void; public _inheritStyleProperty(property: dependencyObservable.Property): void; public _inheritStyleProperties(): void; + public _updateTextDecoration(): void; //@endprivate } diff --git a/ui/text-base/text-base.ts b/ui/text-base/text-base.ts index 028016406..ad6a06971 100644 --- a/ui/text-base/text-base.ts +++ b/ui/text-base/text-base.ts @@ -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(); } } diff --git a/ui/text-field/text-field.ios.ts b/ui/text-field/text-field.ios.ts index d23839e4e..cea7093b7 100644 --- a/ui/text-field/text-field.ios.ts +++ b/ui/text-field/text-field.ios.ts @@ -69,6 +69,9 @@ class UITextFieldDelegateImpl extends NSObject implements UITextFieldDelegate { public textFieldShouldChangeCharactersInRangeReplacementString(textField: UITextField, range: NSRange, replacementString: string): boolean { let owner = this._owner.get(); if (owner) { + + owner.style._updateTextDecoration(); + if (owner.updateTextTrigger === enums.UpdateTextTrigger.textChanged) { if (textField.secureTextEntry && this.firstEdit) { owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, replacementString); diff --git a/ui/text-view/text-view.ios.ts b/ui/text-view/text-view.ios.ts index 700c2dd49..bfa20245a 100644 --- a/ui/text-view/text-view.ios.ts +++ b/ui/text-view/text-view.ios.ts @@ -20,11 +20,13 @@ class UITextViewDelegateImpl extends NSObject implements UITextViewDelegate { } public textViewShouldBeginEditing(textView: UITextView): boolean { + this._owner.style._updateTextDecoration(); this._owner._hideHint(); return true; } public textViewDidEndEditing(textView: UITextView) { + this._owner.style._updateTextDecoration(); if (this._owner.updateTextTrigger === enums.UpdateTextTrigger.focusLost) { this._owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, textView.text); } @@ -34,6 +36,8 @@ class UITextViewDelegateImpl extends NSObject implements UITextViewDelegate { } public textViewDidChange(textView: UITextView) { + this._owner.style._updateTextDecoration(); + if (this._owner.updateTextTrigger === enums.UpdateTextTrigger.textChanged) { this._owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, textView.text); }