white-space CSS support added

This commit is contained in:
Vladimir Enchev
2015-11-11 11:25:55 +02:00
parent 4fddce9d0b
commit 93cf00389e
20 changed files with 180 additions and 63 deletions

View File

@ -189,6 +189,9 @@
<SubType>Designer</SubType>
</Content>
<Content Include="apps\tests\pages\tab-view.xml" />
<Content Include="apps\ui-tests-app\css\white-space.xml">
<SubType>Designer</SubType>
</Content>
<Content Include="apps\ui-tests-app\html-view\html-view.xml">
<SubType>Designer</SubType>
</Content>
@ -239,6 +242,7 @@
<DependentUpon>color.xml</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="apps\ui-tests-app\css\text-decoration.ts" />
<TypeScriptCompile Include="apps\ui-tests-app\css\white-space.ts" />
<TypeScriptCompile Include="apps\ui-tests-app\html-view\html-view.ts">
<DependentUpon>html-view.xml</DependentUpon>
</TypeScriptCompile>

View File

@ -0,0 +1,13 @@
var obj;
export function loaded(args) {
obj = args.object;
}
export function butonTap(args) {
if (obj.style.whiteSpace === "normal") {
obj.style.whiteSpace = "nowrap";
} else if (obj.style.whiteSpace === "nowrap") {
obj.style.whiteSpace = "normal";
}
}

View File

@ -0,0 +1,20 @@
<Page >
<ScrollView>
<StackLayout width="50">
<Button text="Change" tap="butonTap" />
<Label text="Text Text" style.whiteSpace="normal" loaded="loaded"/>
<Label text="Label Normal" style="white-space:normal" />
<Label text="Label Nowrap" style="white-space:nowrap" />
<TextField text="TextField Normal" style="white-space:normal" />
<TextField text="TextField Nowrap" style="white-space:nowrap" />
<TextView text="TextView Normal" style="white-space:normal" />
<TextView text="TextView Nowrap" style="white-space:nowrap" />
<Button text="Button Normal" style="white-space:normal" />
<Button text="Button Nowrap" style="white-space:nowrap" />
</StackLayout>
</ScrollView>
</Page>

View File

@ -90,4 +90,6 @@ examples.set("webview", "web-view/web-view");
examples.set("webtest", "web-view/web-vew-test");
examples.set("decoration", "css/text-decoration");
examples.set("whitespace", "css/white-space");
//VM.set("selected", "tabAll");

View File

@ -334,6 +334,7 @@
"apps/ui-tests-app/css/background.ts",
"apps/ui-tests-app/css/styles.ts",
"apps/ui-tests-app/css/text-decoration.ts",
"apps/ui-tests-app/css/white-space.ts",
"apps/ui-tests-app/dialogs/dialogs.ts",
"apps/ui-tests-app/dialogs/view-model.ts",
"apps/ui-tests-app/font/button.ts",

View File

@ -5,6 +5,7 @@ import proxy = require("ui/core/proxy");
import formattedString = require("text/formatted-string");
import observable = require("data/observable");
import weakEvents = require("ui/core/weak-event-listener");
import enums = require("ui/enums");
var textProperty = new dependencyObservable.Property(
"text",
@ -121,4 +122,11 @@ export class Button extends view.View implements definition.Button {
public _addChildFromBuilder(name: string, value: any): void {
formattedString.FormattedString.addFormattedStringToView(this, name, value);
}
}
}
function onTextWrapPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var v = <view.View>data.object;
v.style.whiteSpace = data.newValue ? enums.WhiteSpace.normal : enums.WhiteSpace.nowrap;
}
(<proxy.PropertyMetadata>Button.textWrapProperty.metadata).onSetNativeValue = onTextWrapPropertyChanged;

View File

@ -5,18 +5,6 @@ import proxy = require("ui/core/proxy");
global.moduleMerge(common, exports);
function onTextWrapPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var btn = <Button>data.object;
if (!btn.android) {
return;
}
btn.android.setSingleLine(data.newValue);
}
// register the setNativeValue callback
(<proxy.PropertyMetadata>common.Button.textWrapProperty.metadata).onSetNativeValue = onTextWrapPropertyChanged;
export class Button extends common.Button {
private _android: android.widget.Button;
private _isPressed: boolean;

View File

@ -16,6 +16,11 @@ declare module "ui/button" {
*/
public static textProperty: dependencyObservable.Property;
/**
* Dependency property used to support binding operations for the text wrapping of the current button instance.
*/
public static textWrapProperty: dependencyObservable.Property;
/**
* String value used when hooking to tap event.
*/

View File

@ -26,18 +26,6 @@ class TapHandlerImpl extends NSObject {
global.moduleMerge(common, exports);
function onTextWrapPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var btn = <Button>data.object;
if (!btn.ios) {
return;
}
btn.ios.titleLabel.lineBreakMode = data.newValue ? NSLineBreakMode.NSLineBreakByWordWrapping : 0;
}
// register the setNativeValue callback
(<proxy.PropertyMetadata>common.Button.textWrapProperty.metadata).onSetNativeValue = onTextWrapPropertyChanged;
export class Button extends common.Button {
private _ios: UIButton;
private _tapHandler: NSObject;

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

@ -437,6 +437,21 @@
*/
export var lineThrough: string;
}
/**
* Specifies different white spaces.
*/
export module WhiteSpace {
/**
* Normal wrap.
*/
export var normal: string;
/**
* No wrap.
*/
export var nowrap: string;
}
/**
* Specifies different font weights.

View File

@ -26,6 +26,11 @@ export module TextDecoration {
export var lineThrough = "line-through";
}
export module WhiteSpace {
export var normal = "normal";
export var nowrap = "nowrap";
}
export module Orientation {
export var horizontal = "horizontal";
export var vertical = "vertical";

View File

@ -2,6 +2,8 @@
import dependencyObservable = require("ui/core/dependency-observable");
import proxy = require("ui/core/proxy");
import textBase = require("ui/text-base");
import enums = require("ui/enums");
import view = require("ui/core/view");
export class Label extends textBase.TextBase implements definition.Label {
public static textWrapProperty = new dependencyObservable.Property(
@ -20,4 +22,11 @@ export class Label extends textBase.TextBase implements definition.Label {
set textWrap(value: boolean) {
this._setValue(Label.textWrapProperty, value);
}
}
}
function onTextWrapPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var v = <view.View>data.object;
v.style.whiteSpace = data.newValue ? enums.WhiteSpace.normal : enums.WhiteSpace.nowrap;
}
(<proxy.PropertyMetadata>Label.textWrapProperty.metadata).onSetNativeValue = onTextWrapPropertyChanged;

View File

@ -2,25 +2,6 @@
import dependencyObservable = require("ui/core/dependency-observable");
import proxy = require("ui/core/proxy");
function onTextWrapPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var label = <Label>data.object;
if (!label.android) {
return;
}
if (data.newValue) {
label.android.setSingleLine(false);
label.android.setEllipsize(null);
}
else {
label.android.setSingleLine(true);
label.android.setEllipsize(android.text.TextUtils.TruncateAt.END);
}
}
// register the setNativeValue callback
(<proxy.PropertyMetadata>common.Label.textWrapProperty.metadata).onSetNativeValue = onTextWrapPropertyChanged;
global.moduleMerge(common, exports);
export class Label extends common.Label {

View File

@ -4,22 +4,7 @@ import dependencyObservable = require("ui/core/dependency-observable");
import proxy = require("ui/core/proxy");
import utils = require("utils/utils");
import viewModule = require("ui/core/view");
function onTextWrapPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var label = <Label>data.object;
if (data.newValue) {
label.ios.lineBreakMode = NSLineBreakMode.NSLineBreakByWordWrapping;
label.ios.numberOfLines = 0;
}
else {
label.ios.lineBreakMode = NSLineBreakMode.NSLineBreakByTruncatingTail;
label.ios.numberOfLines = 1;
}
}
// register the setNativeValue callback
(<proxy.PropertyMetadata>common.Label.textWrapProperty.metadata).onSetNativeValue = onTextWrapPropertyChanged;
import enums = require("ui/enums");
global.moduleMerge(common, exports);
@ -104,7 +89,7 @@ export class Label extends common.Label {
var nativeSize = nativeView.sizeThatFits(CGSizeMake(width, height));
var labelWidth = nativeSize.width;
if (!this.textWrap) {
if (!this.textWrap && this.style.whiteSpace !== enums.WhiteSpace.nowrap) {
labelWidth = Math.min(labelWidth, width);
}

View File

@ -32,6 +32,16 @@ export function textDecorationConverter(value: string): string {
}
}
export function whiteSpaceConverter(value: string): string {
switch (value) {
case enums.WhiteSpace.normal:
case enums.WhiteSpace.nowrap:
return value;
default:
throw new Error("CSS white-space \"" + value + "\" is not supported.");
}
}
export var numberConverter = parseFloat;
export function visibilityConverter(value: string): string {

View File

@ -63,6 +63,7 @@ declare module "ui/styling/style" {
public verticalAlignment: string;
public visibility: string;
public opacity: number;
public whiteSpace: string;
new(parentView: View);

View File

@ -245,6 +245,10 @@ function isTextDecorationValid(value: string): boolean {
return values.indexOf(enums.TextDecoration.none) !== -1 || values.indexOf(enums.TextDecoration.underline) !== -1 || values.indexOf(enums.TextDecoration.lineThrough) !== -1;
}
function isWhiteSpaceValid(value: string): boolean {
return value === enums.WhiteSpace.nowrap || value === enums.WhiteSpace.normal;
}
function onVisibilityChanged(data: PropertyChangeData) {
(<any>data.object)._view._isVisibleCache = data.newValue === enums.Visibility.visible;
}
@ -549,6 +553,13 @@ export class Style extends DependencyObservable implements styling.Style {
this._setValue(textDecorationProperty, value);
}
get whiteSpace(): string {
return this._getValue(whiteSpaceProperty);
}
set whiteSpace(value: string) {
this._setValue(whiteSpaceProperty, value);
}
public _updateTextDecoration() {
if (this._getValue(textDecorationProperty) !== enums.TextDecoration.none) {
this._applyProperty(textDecorationProperty, this._getValue(textDecorationProperty));
@ -810,6 +821,9 @@ export var opacityProperty = new styleProperty.Property("opacity", "opacity",
export var textDecorationProperty = new styleProperty.Property("textDecoration", "text-decoration",
new PropertyMetadata(enums.TextDecoration.none, PropertyMetadataSettings.None, undefined, isTextDecorationValid), converters.textDecorationConverter);
export var whiteSpaceProperty = new styleProperty.Property("whiteSpace", "white-space",
new PropertyMetadata(undefined, AffectsLayout, undefined, isWhiteSpaceValid), converters.whiteSpaceConverter);
// 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

@ -438,6 +438,15 @@ export class TextViewStyler implements definition.stylers.Styler {
setTextDecoration(view._nativeView, enums.TextDecoration.none);
}
// white-space
private static setWhiteSpaceProperty(view: view.View, newValue: any) {
setWhiteSpace(view._nativeView, newValue);
}
private static resetWhiteSpaceProperty(view: view.View, nativeValue: any) {
setWhiteSpace(view._nativeView, enums.WhiteSpace.normal);
}
public static registerHandlers() {
style.registerHandler(style.colorProperty, new stylersCommon.StylePropertyChangedHandler(
TextViewStyler.setColorProperty,
@ -458,6 +467,10 @@ export class TextViewStyler implements definition.stylers.Styler {
TextViewStyler.setTextDecorationProperty,
TextViewStyler.resetTextDecorationProperty), "TextBase");
style.registerHandler(style.whiteSpaceProperty, new stylersCommon.StylePropertyChangedHandler(
TextViewStyler.setWhiteSpaceProperty,
TextViewStyler.resetWhiteSpaceProperty), "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(
@ -478,6 +491,10 @@ export class TextViewStyler implements definition.stylers.Styler {
style.registerHandler(style.textDecorationProperty, new stylersCommon.StylePropertyChangedHandler(
TextViewStyler.setTextDecorationProperty,
TextViewStyler.resetTextDecorationProperty), "Button");
style.registerHandler(style.whiteSpaceProperty, new stylersCommon.StylePropertyChangedHandler(
TextViewStyler.setWhiteSpaceProperty,
TextViewStyler.resetWhiteSpaceProperty), "Button");
}
}
@ -501,6 +518,11 @@ function setTextDecoration(view: android.widget.TextView, value: string) {
}
}
function setWhiteSpace(view: android.widget.TextView, value: string) {
view.setSingleLine(value === enums.WhiteSpace.nowrap);
view.setEllipsize(value === enums.WhiteSpace.nowrap ? android.text.TextUtils.TruncateAt.END : null);
}
export class ActivityIndicatorStyler implements definition.stylers.Styler {
private static setColorProperty(view: view.View, newValue: any) {
var bar = <android.widget.ProgressBar>view._nativeView;

View File

@ -16,7 +16,9 @@ interface TextUIView {
textAlignment: number;
textColor: UIColor;
text : string;
attributedText : NSAttributedString;
attributedText: NSAttributedString;
lineBreakMode: number;
numberOfLines: number;
}
var ignorePropertyHandler = new stylersCommon.StylePropertyChangedHandler(
@ -263,6 +265,15 @@ export class ButtonStyler implements definition.stylers.Styler {
setTextDecoration((<UIButton>view.ios).titleLabel, enums.TextDecoration.none);
}
// white-space
private static setWhiteSpaceProperty(view: view.View, newValue: any) {
setWhiteSpace((<UIButton>view.ios).titleLabel, newValue, view.ios);
}
private static resetWhiteSpaceProperty(view: view.View, nativeValue: any) {
setWhiteSpace((<UIButton>view.ios).titleLabel, enums.WhiteSpace.normal, view.ios);
}
public static registerHandlers() {
style.registerHandler(style.colorProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setColorProperty,
@ -286,6 +297,10 @@ export class ButtonStyler implements definition.stylers.Styler {
style.registerHandler(style.textDecorationProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setTextDecorationProperty,
ButtonStyler.resetTextDecorationProperty), "Button");
style.registerHandler(style.whiteSpaceProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setWhiteSpaceProperty,
ButtonStyler.resetWhiteSpaceProperty), "Button");
}
}
@ -330,6 +345,15 @@ export class TextBaseStyler implements definition.stylers.Styler {
setTextDecoration(view._nativeView, enums.TextDecoration.none);
}
// white-space
private static setWhiteSpaceProperty(view: view.View, newValue: any) {
setWhiteSpace(view._nativeView, newValue);
}
private static resetWhiteSpaceProperty(view: view.View, nativeValue: any) {
setWhiteSpace(view._nativeView, enums.WhiteSpace.normal);
}
// color
private static setColorProperty(view: view.View, newValue: any) {
var ios: TextUIView = <TextUIView>view._nativeView;
@ -365,6 +389,10 @@ export class TextBaseStyler implements definition.stylers.Styler {
style.registerHandler(style.textDecorationProperty, new stylersCommon.StylePropertyChangedHandler(
TextBaseStyler.setTextDecorationProperty,
TextBaseStyler.resetTextDecorationProperty), "TextBase");
style.registerHandler(style.whiteSpaceProperty, new stylersCommon.StylePropertyChangedHandler(
TextBaseStyler.setWhiteSpaceProperty,
TextBaseStyler.resetWhiteSpaceProperty), "TextBase");
}
}
@ -928,6 +956,21 @@ function setTextDecoration(view: TextUIView, value: string) {
}
}
function setWhiteSpace(view: TextUIView, value: string, parentView?: UIView) {
if (value === enums.WhiteSpace.normal) {
view.lineBreakMode = NSLineBreakMode.NSLineBreakByWordWrapping;
view.numberOfLines = 0;
}
else {
if (parentView) {
view.lineBreakMode = NSLineBreakMode.NSLineBreakByTruncatingMiddle;
} else {
view.lineBreakMode = NSLineBreakMode.NSLineBreakByTruncatingTail;
}
view.numberOfLines = 1;
}
}
function setTextDecorationNative(view: TextUIView, value: string | NSAttributedString, attributes: NSMutableDictionary) {
var attributedString: NSMutableAttributedString;

View File

@ -198,6 +198,9 @@
*/
opacity: number;
textDecoration: string;
whiteSpace: string;
//@private
public _beginUpdate();
public _endUpdate();