Fixed: getViewById, TextDecoration

This commit is contained in:
Rossen Hristov
2016-12-15 13:20:25 +02:00
parent 8d573e0304
commit 51e448aa10
16 changed files with 170 additions and 214 deletions

View File

@ -1,60 +1,26 @@
import view = require("ui/core/view");
import label = require("ui/label");
import button = require("ui/button");
import textField = require("ui/text-field");
import textView = require("ui/text-view");
import { EventData, TextBase, TextDecoration } from "ui/text-base";
import { Page } from "ui/page";
export function changeTextButonTap(args) {
var btnChange = <button.Button>args.object;
var lbl = <label.Label>btnChange.parent.getViewById("Label");
var btn = <button.Button>btnChange.parent.getViewById("Button");
var textField = <textField.TextField>btnChange.parent.getViewById("TextField");
var textView = <textView.TextView>btnChange.parent.getViewById("TextView");
const possibleValues = [
TextDecoration.NONE,
TextDecoration.UNDERLINE,
TextDecoration.LINE_THROUGH,
TextDecoration.UNDERLINE_LINE_THROUGH
];
if(lbl.text === "Change text") {
lbl.text = btn.text = textField.text = textView.text = "Text changed";
} else {
lbl.text = btn.text = textField.text = textView.text = "Change text";
}
}
export function butonTap(args) {
var btnChange = <view.View>args.object;
var lbl = <label.Label>btnChange.parent.getViewById("Label");
var btn = <button.Button>btnChange.parent.getViewById("Button");
var textField = <textField.TextField>btnChange.parent.getViewById("TextField");
var textView = <textView.TextView>btnChange.parent.getViewById("TextView");
if (lbl.style.textDecoration === "none") {
lbl.style.textDecoration = "underline";
btn.style.textDecoration = "underline";
textField.style.textDecoration = "underline";
textView.style.textDecoration = "underline";
} else if (lbl.style.textDecoration === "underline") {
lbl.style.textDecoration = "line-through";
btn.style.textDecoration = "line-through";
textField.style.textDecoration = "line-through";
textView.style.textDecoration = "line-through";
} else if (lbl.style.textDecoration === "line-through") {
lbl.style.textDecoration = "line-through underline";
btn.style.textDecoration = "line-through underline";
textField.style.textDecoration = "line-through underline";
textView.style.textDecoration = "line-through underline";
} else if (lbl.style.textDecoration === "line-through underline") {
lbl.style.textDecoration = "line-through underline none";
btn.style.textDecoration = "line-through underline none";
textField.style.textDecoration = "line-through underline none";
textView.style.textDecoration = "line-through underline none";
} else if (lbl.style.textDecoration === "line-through underline none") {
lbl.style.textDecoration = "none";
btn.style.textDecoration = "none";
textField.style.textDecoration = "none";
textView.style.textDecoration = "none";
if(lbl.text === "Change text") {
lbl.text = btn.text = textField.text = textView.text = "Text changed";
} else {
lbl.text = btn.text = textField.text = textView.text = "Change text";
}
}
export function butonTap(args: EventData) {
let page = (<TextBase>args.object).page;
let lbl = <TextBase>page.getViewById("Label");
let btn = <TextBase>page.getViewById("Button");
let textField = <TextBase>page.getViewById("TextField");
let textView = <TextBase>page.getViewById("TextView");
let currentIndex = possibleValues.indexOf(lbl.textDecoration);
let newIndex = (currentIndex + 1) % possibleValues.length;
let newValue = <TextDecoration>possibleValues[newIndex];
lbl.textDecoration = newValue;
btn.textDecoration = newValue;
textField.textDecoration = newValue;
textView.textDecoration = newValue;
}

View File

@ -1,36 +1,9 @@
<Page >
<Page>
<StackLayout>
<!--<Button id="ChangeText" automationText="Change text" text="Change text" tap="changeTextButonTap" />-->
<Button id="Change" automationText="Change" text="Change" tap="butonTap" />
<Label id="Label" automationText="Label" text="Label" style.textDecoration="none" />
<Button id="Button" automationText="Button" text="Button" style.textDecoration="none" />
<TextField id="TextField" automationText="TextField" text="TextField" style.textDecoration="none" />
<TextView id="TextView" automationText="TextView" text="TextView" style.textDecoration="none" />
<!--
<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" />
-->
<Label id="Label" automationText="Label" text="Label" textDecoration="none" />
<Button id="Button" automationText="Button" text="Button" textDecoration="none" />
<TextField id="TextField" automationText="TextField" text="TextField" textDecoration="none" />
<TextView id="TextView" automationText="TextView" text="TextView" textDecoration="none" />
</StackLayout>
</Page>

View File

@ -35,30 +35,15 @@ export function butonTap(args) {
btn.style.textTransform = "uppercase";
textField.style.textTransform = "uppercase";
textView.style.textTransform = "uppercase";
} else if (lbl.style.textTransform === "uppercase" && lbl.style.textDecoration !== "line-through underline") {
} else if (lbl.style.textTransform === "uppercase") {
lbl.style.textTransform = "lowercase";
btn.style.textTransform = "lowercase";
textField.style.textTransform = "lowercase";
textView.style.textTransform = "lowercase";
} else if (lbl.style.textTransform === "lowercase") {
// lbl.style.textTransform = "uppercase";
// btn.style.textTransform = "uppercase";
// textField.style.textTransform = "uppercase";
// textView.style.textTransform = "uppercase";
// lbl.style.textDecoration = "line-through underline";
// btn.style.textDecoration = "line-through underline";
// textField.style.textDecoration = "line-through underline";
// textView.style.textDecoration = "line-through underline";
//} else if (lbl.style.textTransform === "uppercase" && lbl.style.textDecoration === "line-through underline") {
lbl.style.textTransform = "none";
btn.style.textTransform = "none";
textField.style.textTransform = "none";
textView.style.textTransform = "none";
//lbl.style.textDecoration = "none";
//btn.style.textDecoration = "none";
//textField.style.textDecoration = "none";
//textView.style.textDecoration = "none";
}
}

View File

@ -30,6 +30,7 @@
/// <reference path="text/text.d.ts" />
/// <reference path="timer/timer.d.ts" />
/// <reference path="trace/trace.d.ts" />
/// <reference path="ui/definitions.d.ts" />
/// <reference path="ui/action-bar/action-bar.d.ts" />
/// <reference path="ui/activity-indicator/activity-indicator.d.ts" />
/// <reference path="ui/animation/animation.d.ts" />

View File

@ -50,6 +50,47 @@ export function isEventOrGesture(name: string, view: ViewBaseDefinition): boolea
return false;
}
export function getViewById(view: ViewBaseDefinition, id: string): ViewBaseDefinition {
if (!view) {
return undefined;
}
if (view.id === id) {
return view;
}
let retVal: ViewBaseDefinition;
const descendantsCallback = function (child: ViewBaseDefinition): boolean {
if (child.id === id) {
retVal = child;
// break the iteration by returning false
return false;
}
return true;
}
eachDescendant(view, descendantsCallback);
return retVal;
}
export function eachDescendant(view: ViewBaseDefinition, callback: (child: ViewBaseDefinition) => boolean) {
if (!callback || !view) {
return;
}
let continueIteration: boolean;
let localCallback = function (child: ViewBaseDefinition): boolean {
continueIteration = callback(child);
if (continueIteration) {
child.eachChild(localCallback);
}
return continueIteration;
}
view.eachChild(localCallback);
}
export class ViewBase extends Observable implements ViewBaseDefinition {
private _updatingJSPropertiesDict = {};
private _style: Style;
@ -87,6 +128,10 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
return this._isLoaded;
}
getViewById<T extends ViewBaseDefinition>(id: string): T {
return <T>getViewById(this, id);
}
get page(): ViewBaseDefinition {
if (this.parent) {
return this.parent.page;
@ -493,3 +538,14 @@ function resetStyles(view: ViewBase): void {
export const idProperty = new Property<ViewBase, string>({ name: "id", valueChanged: (view, oldValue, newValue) => resetStyles(view) });
idProperty.register(ViewBase);
export function makeValidator<T>(...values: T[]): (value: any) => value is T {
const set = new Set(values);
return (value: any): value is T => set.has(value);
}
export function makeParser<T>(isValid: (value: any) => boolean, def: T): (value: any) => T {
return value => {
const lower = value && value.toLowerCase();
return isValid(lower) ? lower : def;
}
}

View File

@ -49,47 +49,6 @@ Style.prototype.effectiveBorderRightWidth = 0;
Style.prototype.effectiveBorderBottomWidth = 0;
Style.prototype.effectiveBorderLeftWidth = 0;
export function getViewById(view: ViewDefinition, id: string): ViewDefinition {
if (!view) {
return undefined;
}
if (view.id === id) {
return view;
}
let retVal: ViewDefinition;
const descendantsCallback = function (child: ViewDefinition): boolean {
if (child.id === id) {
retVal = child;
// break the iteration by returning false
return false;
}
return true;
}
eachDescendant(view, descendantsCallback);
return retVal;
}
export function eachDescendant(view: ViewDefinition, callback: (child: ViewDefinition) => boolean) {
if (!callback || !view) {
return;
}
let continueIteration: boolean;
let localCallback = function (child: ViewDefinition): boolean {
continueIteration = callback(child);
if (continueIteration) {
child._eachChildView(localCallback);
}
return continueIteration;
}
view._eachChildView(localCallback);
}
export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator {
let stateEventNames = pseudoClasses.map(s => ":" + s);
let listeners = Symbol("listeners");
@ -233,10 +192,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
}
}
getViewById<T extends ViewDefinition>(id: string): T {
return <T>getViewById(this, id);
}
// START Style property shortcuts
get borderColor(): string | Color {
return this.style.borderColor;

View File

@ -41,14 +41,6 @@ declare module "ui/core/view" {
export const zeroLength: Length;
export function getLengthEffectiveValue(param: Length): number;
/**
* Gets a child view by id.
* @param view - The parent (container) view of the view to look for.
* @param id - The id of the view to look for.
* Returns an instance of a view (if found), otherwise undefined.
*/
export function getViewById(view: View, id: string): View;
/**
* Converts string into boolean value.
* Throws error if value is not 'true' or 'false'.
@ -350,16 +342,6 @@ declare module "ui/core/view" {
*/
isUserInteractionEnabled: boolean;
/**
* Gets or sets the id for this view.
*/
id: string;
/**
* Gets or sets the CSS class name for this view.
*/
className: string;
/**
* Gets is layout is valid. This is a read-only property.
*/
@ -475,11 +457,6 @@ declare module "ui/core/view" {
public static combineMeasuredStates(curState: number, newState): number;
/**
* Returns the child view with the specified id.
*/
public getViewById<T extends View>(id: string): T;
/**
* Tries to focus the view.
* Returns a value indicating whether this view or one of its descendants actually took focus.

View File

@ -29,6 +29,14 @@ declare module "ui/core/view-base" {
export function getAncestor(view: ViewBase, criterion: string | Function): ViewBase;
export function isEventOrGesture(name: string, view: ViewBase): boolean;
/**
* Gets a child view by id.
* @param view - The parent (container) view of the view to look for.
* @param id - The id of the view to look for.
* Returns an instance of a view (if found), otherwise undefined.
*/
export function getViewById(view: ViewBase, id: string): ViewBase;
export class ViewBase extends Observable {
/**
* String value used when hooking to loaded event.
@ -50,6 +58,21 @@ declare module "ui/core/view-base" {
*/
public readonly parent: ViewBase;
/**
* Gets or sets the id for this view.
*/
public id: string;
/**
* Returns the child view with the specified id.
*/
public getViewById<T extends ViewBase>(id: string): T;
/**
* Gets or sets the CSS class name for this view.
*/
public className: string;
/**
* Gets owner page. This is a read-only property.
*/
@ -106,6 +129,9 @@ declare module "ui/core/view-base" {
export const idProperty: Property<ViewBase, string>;
export const classNameProperty: Property<ViewBase, string>;
export const bindingContextProperty: InheritedProperty<ViewBase, any>;
export function makeValidator<T>(...values: T[]): (value: any) => value is T;
export function makeParser<T>(isValid: (value: any) => boolean, def: T): (value: any) => T;
}
declare module "ui/core/properties" {

View File

@ -1,5 +1,5 @@
import * as flexbox from "ui/layouts/flexbox-layout";
import { LayoutBase, View, Style, Property, CssProperty, isIOS, ShorthandProperty } from "ui/layouts/layout-base";
import { LayoutBase, View, Style, Property, CssProperty, isIOS, ShorthandProperty, makeValidator, makeParser} from "ui/layouts/layout-base";
export * from "ui/layouts/layout-base";
@ -17,16 +17,16 @@ export const ORDER_DEFAULT = 1;
export const FLEX_GROW_DEFAULT = 0.0;
export const FLEX_SHRINK_DEFAULT = 1.0;
function makeValidator<T>(...values: T[]): (value: any) => value is T {
const set = new Set(values);
return (value: any): value is T => set.has(value);
}
function makeParser<T>(isValid: (value: any) => boolean, def: T): (value: any) => T {
return value => {
const lower = value && value.toLowerCase();
return isValid(lower) ? lower : def;
}
}
// function makeValidator<T>(...values: T[]): (value: any) => value is T {
// const set = new Set(values);
// return (value: any): value is T => set.has(value);
// }
// function makeParser<T>(isValid: (value: any) => boolean, def: T): (value: any) => T {
// return value => {
// const lower = value && value.toLowerCase();
// return isValid(lower) ? lower : def;
// }
// }
export type FlexDirection = "row" | "row-reverse" | "column" | "column-reverse";
export namespace FlexDirection {

View File

@ -29,7 +29,12 @@ export function textAlignConverter(value: string): string {
export function textDecorationConverter(value: string): string {
const values = (value + "").split(" ");
if (values.indexOf("none") !== -1 || values.indexOf("underline") !== -1 || values.indexOf("lineThrough") !== -1) {
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.");

View File

@ -1,5 +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";
export interface Thickness {
left: number;
@ -86,7 +87,7 @@ declare module "ui/styling/style" {
public letterSpacing: number;
public textAlignment: "left" | "center" | "right";
public textDecoration: "none" | "underline" | "lineThrough";
public textDecoration: TextDecoration;
public textTransform: "none" | "capitalize" | "uppercase" | "lowercase";
public whiteSpace: "normal" | "nowrap";

View File

@ -6,7 +6,9 @@ import { resetStyleProperties } from "ui/core/properties";
import {
FlexDirection, FlexWrap, JustifyContent, AlignItems, AlignContent,
Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf
} from "ui/layouts/flexbox-layout"
} from "ui/layouts/flexbox-layout";
import { TextDecoration } from "ui/text-base";
export class Style extends Observable implements StyleDefinition {
constructor(public view: ViewBase) {
@ -64,7 +66,7 @@ export class Style extends Observable implements StyleDefinition {
public letterSpacing: number;
public textAlignment: "left" | "center" | "right";
public textDecoration: "none" | "underline" | "lineThrough";
public textDecoration: TextDecoration;
public textTransform: "none" | "capitalize" | "uppercase" | "lowercase";
public whiteSpace: "normal" | "nowrap";

View File

@ -1,5 +1,5 @@
import { TextBase as TextBaseDefinition } from "ui/text-base";
import { View, AddChildFromBuilder, Property, CssProperty, InheritedCssProperty, Style, isIOS, Observable } from "ui/core/view";
import { View, AddChildFromBuilder, Property, CssProperty, InheritedCssProperty, Style, isIOS, Observable, makeValidator, makeParser} from "ui/core/view";
import { PropertyChangeData } from "data/observable";
import { FormattedString, FormattedStringView } from "text/formatted-string";
import { addWeakEventListener, removeWeakEventListener } from "ui/core/weak-event-listener";
@ -78,10 +78,10 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition,
this.style.textAlignment = value;
}
get textDecoration(): "none" | "underline" | "lineThrough" {
get textDecoration(): TextDecoration {
return this.style.textDecoration;
}
set textDecoration(value: "none" | "underline" | "lineThrough") {
set textDecoration(value: TextDecoration) {
this.style.textDecoration = value;
}
@ -135,21 +135,19 @@ export const textAlignmentProperty = new InheritedCssProperty<Style, "left" | "c
});
textAlignmentProperty.register(Style);
export const textDecorationProperty = new CssProperty<Style, "none" | "underline" | "line-through">({
name: "textDecoration", cssName: "text-decoration", defaultValue: "none", valueConverter: (value) => {
if (value === null || value === undefined || value === "") {
value = "none";
}
// TextDecoration
export type TextDecoration = "none" | "underline" | "line-through" | "underline line-through";
export namespace TextDecoration {
export const NONE: "none" = "none";
export const UNDERLINE: "underline" = "underline";
export const LINE_THROUGH: "line-through" = "line-through";
export const UNDERLINE_LINE_THROUGH: "underline line-through" = "underline line-through";
(value + "").split(" ").forEach((v, i, arr) => {
if (v !== "none" && v !== "underline" && v !== "line-through") {
throw new Error(`CSS text-decoration ${value} is not supported.`);
}
});
return <any>value;
}
});
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});
textDecorationProperty.register(Style);
export const textTransformProperty = new CssProperty<Style, "none" | "capitalize" | "uppercase" | "lowercase">({

View File

@ -1,7 +1,7 @@
import {
TextBaseCommon, textProperty, formattedTextProperty, textAlignmentProperty, textDecorationProperty,
textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty, whiteSpaceProperty,
Font, Color, FormattedString
Font, Color, FormattedString, TextDecoration
} from "./text-base-common";
export * from "./text-base-common";
@ -163,10 +163,10 @@ export class TextBase extends TextBaseCommon {
}
}
get [textDecorationProperty.native](): "none" | "underline" | "line-through" {
get [textDecorationProperty.native](): TextDecoration {
return "none";
}
set [textDecorationProperty.native](value: "none" | "underline" | "line-through") {
set [textDecorationProperty.native](value: TextDecoration) {
let flags = 0;
let values = (value + "").split(" ");

View File

@ -37,7 +37,7 @@
/**
* Gets or sets text decorations style property.
*/
textDecoration: "none" | "underline" | "lineThrough";
textDecoration: TextDecoration;
/**
* Gets or sets text transform style property.
@ -68,6 +68,16 @@
//@endprivate
}
export type TextDecoration = "none" | "underline" | "line-through" | "underline line-through";
export namespace TextDecoration {
export const NONE: "none";
export const UNDERLINE: "underline";
export const LINE_THROUGH: "line-through";
export const UNDERLINE_LINE_THROUGH: "underline line-through";
export function isValid(value: any): boolean;
export function parse(value: string): TextDecoration;
}
export type TextTransform = "none" | "capitalize" | "uppercase" | "lowercase";
export function getTransformedText(text: string, transform: TextTransform): string;
@ -76,7 +86,7 @@
export const formattedTextProperty: Property<TextBase, FormattedString>;
export const textAlignmentProperty: InheritedCssProperty<Style, "left" | "center" | "right">;
export const textDecorationProperty: CssProperty<Style, "none" | "underline" | "line-through">;
export const textDecorationProperty: CssProperty<Style, TextDecoration>;
export const textTransformProperty: CssProperty<Style, TextTransform>;
export const whiteSpaceProperty: CssProperty<Style, "normal" | "nowrap">;
export const letterSpacingProperty: CssProperty<Style, number>;

View File

@ -1,6 +1,7 @@
import {
TextBaseCommon, textProperty, formattedTextProperty, textAlignmentProperty, textDecorationProperty,
textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty, Font, Color, FormattedString
textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty, Font, Color, FormattedString,
TextDecoration
} from "./text-base-common";
export * from "./text-base-common";
@ -244,10 +245,10 @@ export class TextBase extends TextBaseCommon {
}
}
get [textDecorationProperty.native](): string {
get [textDecorationProperty.native](): TextDecoration {
return "none";
}
set [textDecorationProperty.native](value: string) {
set [textDecorationProperty.native](value: TextDecoration) {
if (this.formattedText) {
setFormattedTextDecorationAndTransform(this.formattedText, this.nativeView, value, this.style.textTransform, this.style.letterSpacing);
} else {