refactoring circular imports

This commit is contained in:
Hristo Hristov
2017-03-06 14:01:22 +02:00
parent 347755367e
commit ea22eb9c20
82 changed files with 2229 additions and 2188 deletions

View File

@ -9,7 +9,10 @@
"appRoot": "${workspaceRoot}", "appRoot": "${workspaceRoot}",
"sourceMaps": true, "sourceMaps": true,
"watch": true, "watch": true,
"stopOnEntry": true "stopOnEntry": true,
"tnsArgs": [
"--sync-all-files"
]
}, },
{ {
"name": "Attach on iOS", "name": "Attach on iOS",
@ -28,7 +31,10 @@
"appRoot": "${workspaceRoot}", "appRoot": "${workspaceRoot}",
"sourceMaps": true, "sourceMaps": true,
"watch": true, "watch": true,
"stopOnEntry": true "stopOnEntry": false,
"tnsArgs": [
"--sync-all-files"
]
}, },
{ {
"name": "Attach on Android", "name": "Attach on Android",

View File

@ -3,6 +3,8 @@ import * as TKUnit from "./TKUnit";
import * as http from "http"; import * as http from "http";
import * as types from "utils/types"; import * as types from "utils/types";
import * as fs from "file-system"; import * as fs from "file-system";
import { addHeader } from "http/http-request";
require("globals"); require("globals");
// >> http-require // >> http-require
@ -512,10 +514,10 @@ export var test_request_headersWithSameKeyAddedProperly = function (done) {
var value1 = "value1"; var value1 = "value1";
var value2 = "value2"; var value2 = "value2";
var headers = {}; var headers: http.Headers = {};
(<any>http).addHeader(headers, keyName, value1); addHeader(headers, keyName, value1);
(<any>http).addHeader(headers, keyName, value2); addHeader(headers, keyName, value2);
try { try {
TKUnit.assertTrue(Array.isArray(headers[keyName])); TKUnit.assertTrue(Array.isArray(headers[keyName]));

View File

@ -1,7 +1,7 @@
import * as buttonModule from "ui/button"; import * as buttonModule from "ui/button";
import * as colorModule from "color"; import * as colorModule from "color";
import * as utilsModule from "utils/utils";
import * as enums from "ui/enums"; import * as enums from "ui/enums";
import { getColor } from "../helper";
export function getNativeText(button: buttonModule.Button): string { export function getNativeText(button: buttonModule.Button): string {
return button.ios.titleForState(UIControlState.Normal); return button.ios.titleForState(UIControlState.Normal);
@ -16,11 +16,11 @@ export function getNativeFontSize(button: buttonModule.Button): number {
} }
export function getNativeColor(button: buttonModule.Button): colorModule.Color { export function getNativeColor(button: buttonModule.Button): colorModule.Color {
return utilsModule.ios.getColor(button.ios.titleColorForState(UIControlState.Normal)); return getColor(button.ios.titleColorForState(UIControlState.Normal));
} }
export function getNativeBackgroundColor(button: buttonModule.Button): colorModule.Color { export function getNativeBackgroundColor(button: buttonModule.Button): colorModule.Color {
return utilsModule.ios.getColor(button.ios.backgroundColor); return getColor(button.ios.backgroundColor);
} }
export function getNativeTextAlignment(button: buttonModule.Button): string { export function getNativeTextAlignment(button: buttonModule.Button): string {

View File

@ -11,12 +11,28 @@ import * as formattedStringModule from "text/formatted-string";
import * as spanModule from "text/span"; import * as spanModule from "text/span";
import { ActionBar } from "ui/action-bar"; import { ActionBar } from "ui/action-bar";
import { unsetValue } from "ui/core/view"; import { unsetValue } from "ui/core/view";
import { Color } from "color";
var DELTA = 0.1; var DELTA = 0.1;
export var ASYNC = 0.2; export var ASYNC = 0.2;
export var MEMORY_ASYNC = 2; export var MEMORY_ASYNC = 2;
export function getColor(uiColor: UIColor): Color {
var redRef = new interop.Reference<number>();
var greenRef = new interop.Reference<number>();
var blueRef = new interop.Reference<number>();
var alphaRef = new interop.Reference<number>();
uiColor.getRedGreenBlueAlpha(redRef, greenRef, blueRef, alphaRef);
var red = redRef.value * 255;
var green = greenRef.value * 255;
var blue = blueRef.value * 255;
var alpha = alphaRef.value * 255;
return new Color(alpha, red, green, blue);
}
function clearPage(): void { function clearPage(): void {
let newPage = getCurrentPage(); let newPage = getCurrentPage();
if (!newPage) { if (!newPage) {

View File

@ -5,6 +5,7 @@ import { isIOS, isAndroid } from "platform";
import { PropertyChangeData } from "data/observable"; import { PropertyChangeData } from "data/observable";
import * as utils from "utils/utils"; import * as utils from "utils/utils";
import * as TKUnit from "../../TKUnit"; import * as TKUnit from "../../TKUnit";
import { getColor } from "../helper";
// >> img-require // >> img-require
import * as ImageModule from "ui/image"; import * as ImageModule from "ui/image";
@ -384,7 +385,7 @@ export const test_tintColor = function () {
TKUnit.assert(tintColor === null, "tintColor expected to be set to null"); TKUnit.assert(tintColor === null, "tintColor expected to be set to null");
} }
else if (image.ios) { else if (image.ios) {
const imageColor = utils.ios.getColor(testImage.ios.tintColor); const imageColor = getColor(testImage.ios.tintColor);
TKUnit.assert(!imageColor.equals(colorRed), "imageColor expected to be different than tintColor"); TKUnit.assert(!imageColor.equals(colorRed), "imageColor expected to be different than tintColor");
} }
image.tintColor = colorRed; image.tintColor = colorRed;
@ -393,7 +394,7 @@ export const test_tintColor = function () {
TKUnit.assert(testImage.android.getColorFilter() !== null, "tintColor expected to be set to a nonnull value"); TKUnit.assert(testImage.android.getColorFilter() !== null, "tintColor expected to be set to a nonnull value");
} }
else if (image.ios) { else if (image.ios) {
const imageColor = utils.ios.getColor(testImage.ios.tintColor); const imageColor = getColor(testImage.ios.tintColor);
TKUnit.assert(imageColor.equals(colorRed), "tintColor expected to be set to: " + colorRed); TKUnit.assert(imageColor.equals(colorRed), "tintColor expected to be set to: " + colorRed);
} }
}; };

View File

@ -1,7 +1,7 @@
import * as labelModule from "ui/label"; import * as labelModule from "ui/label";
import * as enums from "ui/enums"; import * as enums from "ui/enums";
import * as colorModule from "color"; import * as colorModule from "color";
import * as utilsModule from "utils/utils"; import { getColor } from "../helper";
export function getNativeTextAlignment(label: labelModule.Label): string { export function getNativeTextAlignment(label: labelModule.Label): string {
switch (label.ios.textAlignment) { switch (label.ios.textAlignment) {
@ -22,5 +22,5 @@ export function getNativeBackgroundColor(label: labelModule.Label): colorModule.
return undefined; return undefined;
} }
var uiColor = UIColor.colorWithCGColor(layer.backgroundColor); var uiColor = UIColor.colorWithCGColor(layer.backgroundColor);
return utilsModule.ios.getColor(uiColor); return getColor(uiColor);
} }

View File

@ -239,13 +239,13 @@ export class LabelTest extends testModule.UITest<LabelModule.Label> {
actualTextSize = testLabel.ios.font.pointSize; actualTextSize = testLabel.ios.font.pointSize;
TKUnit.assertEqual(actualTextSize, fontSize, "Wrong native FontSize"); TKUnit.assertEqual(actualTextSize, fontSize, "Wrong native FontSize");
normalColor = utils.ios.getColor(testLabel.ios.textColor); normalColor = helper.getColor(testLabel.ios.textColor);
expColor = new colorModule.Color(color); expColor = new colorModule.Color(color);
TKUnit.assertEqual(normalColor.hex, expColor.hex); TKUnit.assertEqual(normalColor.hex, expColor.hex);
const cgColor = (<UILabel>testLabel.ios).layer.backgroundColor; const cgColor = (<UILabel>testLabel.ios).layer.backgroundColor;
const uiColor = UIColor.colorWithCGColor(cgColor); const uiColor = UIColor.colorWithCGColor(cgColor);
actualBackgroundColor = utils.ios.getColor(uiColor); actualBackgroundColor = helper.getColor(uiColor);
expBackgroundColor = new colorModule.Color(backgroundColor); expBackgroundColor = new colorModule.Color(backgroundColor);
TKUnit.assertEqual(actualBackgroundColor.hex, expBackgroundColor.hex); TKUnit.assertEqual(actualBackgroundColor.hex, expBackgroundColor.hex);
} }

View File

@ -1,9 +1,9 @@
import { SearchBar } from "ui/search-bar"; import { SearchBar } from "ui/search-bar";
import { Color } from "color"; import { Color } from "color";
import * as utils from "utils/utils"; import { getColor } from "../helper";
export function getNativeHintColor(searchBar: SearchBar): Color { export function getNativeHintColor(searchBar: SearchBar): Color {
return (<any>searchBar)._placeholderLabel ? utils.ios.getColor((<any>searchBar)._placeholderLabel.textColor) : undefined; return (<any>searchBar)._placeholderLabel ? getColor((<any>searchBar)._placeholderLabel.textColor) : undefined;
} }
export function getNativeFontSize(searchBar: SearchBar): number { export function getNativeFontSize(searchBar: SearchBar): number {
return (<any>searchBar)._textField ? (<any>searchBar)._textField.font.pointSize : undefined; return (<any>searchBar)._textField ? (<any>searchBar)._textField.font.pointSize : undefined;

View File

@ -1,6 +1,6 @@
import * as textFieldModule from "ui/text-field"; import * as textFieldModule from "ui/text-field";
import * as colorModule from "color"; import * as colorModule from "color";
import * as utilsModule from "utils/utils"; import { getColor } from "../helper";
import * as enums from "ui/enums"; import * as enums from "ui/enums";
export function getNativeText(textField: textFieldModule.TextField): string { export function getNativeText(textField: textFieldModule.TextField): string {
@ -20,15 +20,15 @@ export function getNativeFontSize(textField: textFieldModule.TextField): number
} }
export function getNativeColor(textField: textFieldModule.TextField): colorModule.Color { export function getNativeColor(textField: textFieldModule.TextField): colorModule.Color {
return utilsModule.ios.getColor(textField.ios.textColor); return getColor(textField.ios.textColor);
} }
export function getNativePlaceholderColor(textField: textFieldModule.TextField): colorModule.Color { export function getNativePlaceholderColor(textField: textFieldModule.TextField): colorModule.Color {
return utilsModule.ios.getColor(textField.ios.attributedPlaceholder.attributeAtIndexEffectiveRange(NSForegroundColorAttributeName, 0, null)); return getColor(textField.ios.attributedPlaceholder.attributeAtIndexEffectiveRange(NSForegroundColorAttributeName, 0, null));
} }
export function getNativeBackgroundColor(textField: textFieldModule.TextField): colorModule.Color { export function getNativeBackgroundColor(textField: textFieldModule.TextField): colorModule.Color {
return utilsModule.ios.getColor(textField.ios.backgroundColor); return getColor(textField.ios.backgroundColor);
} }
export function getNativeTextAlignment(textField: textFieldModule.TextField): string { export function getNativeTextAlignment(textField: textFieldModule.TextField): string {

View File

@ -1,6 +1,6 @@
import * as textViewModule from "ui/text-view"; import * as textViewModule from "ui/text-view";
import * as colorModule from "color"; import * as colorModule from "color";
import * as utilsModule from "utils/utils"; import { getColor } from "../helper";
import * as enums from "ui/enums"; import * as enums from "ui/enums";
export function getNativeText(textView: textViewModule.TextView): string { export function getNativeText(textView: textViewModule.TextView): string {
@ -25,11 +25,11 @@ export function getNativeFontSize(textView: textViewModule.TextView): number {
} }
export function getNativeColor(textView: textViewModule.TextView): colorModule.Color { export function getNativeColor(textView: textViewModule.TextView): colorModule.Color {
return utilsModule.ios.getColor(textView.ios.textColor); return getColor(textView.ios.textColor);
} }
export function getNativeBackgroundColor(textView: textViewModule.TextView): colorModule.Color { export function getNativeBackgroundColor(textView: textViewModule.TextView): colorModule.Color {
return utilsModule.ios.getColor(textView.ios.backgroundColor); return getColor(textView.ios.backgroundColor);
} }
export function getNativeTextAlignment(textView: textViewModule.TextView): string { export function getNativeTextAlignment(textView: textViewModule.TextView): string {

View File

@ -14,7 +14,6 @@ import "globals";
import { NativeScriptError, UnhandledErrorEventData, iOSApplication, AndroidApplication, CssChangedEventData } from "application"; import { NativeScriptError, UnhandledErrorEventData, iOSApplication, AndroidApplication, CssChangedEventData } from "application";
import { NavigationEntry } from "ui/frame"; import { NavigationEntry } from "ui/frame";
import "../bundle-entry-points";
export const launchEvent = "launch"; export const launchEvent = "launch";
export const suspendEvent = "suspend"; export const suspendEvent = "suspend";
@ -62,4 +61,4 @@ export function addCss(cssText: string): void {
global.__onUncaughtError = function (error: NativeScriptError) { global.__onUncaughtError = function (error: NativeScriptError) {
events.notify(<UnhandledErrorEventData>{ eventName: uncaughtErrorEvent, object: app, android: error, ios: error, error: error }); events.notify(<UnhandledErrorEventData>{ eventName: uncaughtErrorEvent, object: app, android: error, ios: error, error: error });
} }

View File

@ -185,16 +185,16 @@ export class Observable implements ObservableDefinition {
} }
class ObservableFromObject extends Observable { class ObservableFromObject extends Observable {
public _map: Map<string, Object> = new Map<string, Object>(); public _map = {};
public set(name: string, value: any) { public set(name: string, value: any) {
const currentValue = this._map.get(name); const currentValue = this._map[name];
if (currentValue === value) { if (currentValue === value) {
return; return;
} }
const newValue = WrappedValue.unwrap(value); const newValue = WrappedValue.unwrap(value);
this._map.set(name, newValue); this._map[name] = newValue;
this.notifyPropertyChange(name, newValue); this.notifyPropertyChange(name, newValue);
} }
} }
@ -202,7 +202,7 @@ class ObservableFromObject extends Observable {
function defineNewProperty(target: ObservableFromObject, propertyName: string): void { function defineNewProperty(target: ObservableFromObject, propertyName: string): void {
Object.defineProperty(target, propertyName, { Object.defineProperty(target, propertyName, {
get: function () { get: function () {
return target._map.get(propertyName); return target._map[propertyName];
}, },
set: function (value) { set: function (value) {
target.set(propertyName, value); target.set(propertyName, value);

View File

@ -116,4 +116,4 @@ interface Array<T> {
//Dialogs //Dialogs
declare function alert(message?: any): void; declare function alert(message?: any): void;
declare function confirm(message?: string): boolean; declare function confirm(message?: string): boolean;

View File

@ -6,7 +6,12 @@ import * as platformModule from "platform";
import * as fsModule from "file-system"; import * as fsModule from "file-system";
// this is imported for definition purposes only // this is imported for definition purposes only
import * as http from "http"; import { Headers, HttpRequestOptions, HttpResponse } from "http";
export const enum HttpResponseEncoding {
UTF8,
GBK
}
function parseJSON(source: string): any { function parseJSON(source: string): any {
var src = source.trim(); var src = source.trim();
@ -58,7 +63,7 @@ function onRequestComplete(requestId: number, result: org.nativescript.widgets.A
} }
// read the headers // read the headers
var headers: http.Headers = {}; var headers: Headers = {};
if (result.headers) { if (result.headers) {
var jHeaders = result.headers; var jHeaders = result.headers;
var length = jHeaders.size(); var length = jHeaders.size();
@ -66,15 +71,14 @@ function onRequestComplete(requestId: number, result: org.nativescript.widgets.A
var pair: org.nativescript.widgets.Async.Http.KeyValuePair; var pair: org.nativescript.widgets.Async.Http.KeyValuePair;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
pair = jHeaders.get(i); pair = jHeaders.get(i);
addHeader(headers, pair.key, pair.value);
(<any>http).addHeader(headers, pair.key, pair.value);
} }
} }
callbacks.resolveCallback({ callbacks.resolveCallback({
content: { content: {
raw: result.raw, raw: result.raw,
toString: (encoding?: http.HttpResponseEncoding) => { toString: (encoding?: HttpResponseEncoding) => {
let str: string; let str: string;
if (encoding) { if (encoding) {
str = decodeResponse(result.raw, encoding); str = decodeResponse(result.raw, encoding);
@ -87,7 +91,7 @@ function onRequestComplete(requestId: number, result: org.nativescript.widgets.A
throw new Error("Response content may not be converted to string"); throw new Error("Response content may not be converted to string");
} }
}, },
toJSON: (encoding?: http.HttpResponseEncoding) => { toJSON: (encoding?: HttpResponseEncoding) => {
let str: string; let str: string;
if (encoding) { if (encoding) {
str = decodeResponse(result.raw, encoding); str = decodeResponse(result.raw, encoding);
@ -136,7 +140,7 @@ function onRequestComplete(requestId: number, result: org.nativescript.widgets.A
}); });
} }
function buildJavaOptions(options: http.HttpRequestOptions) { function buildJavaOptions(options: HttpRequestOptions) {
if (typeof options.url !== "string") { if (typeof options.url !== "string") {
throw new Error("Http request must provide a valid url."); throw new Error("Http request must provide a valid url.");
} }
@ -179,13 +183,13 @@ function buildJavaOptions(options: http.HttpRequestOptions) {
return javaOptions; return javaOptions;
} }
export function request(options: http.HttpRequestOptions): Promise<http.HttpResponse> { export function request(options: HttpRequestOptions): Promise<HttpResponse> {
if (options === undefined || options === null) { if (options === undefined || options === null) {
// TODO: Shouldn't we throw an error here - defensive programming // TODO: Shouldn't we throw an error here - defensive programming
return; return;
} }
return new Promise<http.HttpResponse>((resolve, reject) => {
return new Promise<HttpResponse>((resolve, reject) => {
try { try {
// initialize the options // initialize the options
var javaOptions = buildJavaOptions(options); var javaOptions = buildJavaOptions(options);
@ -210,10 +214,22 @@ export function request(options: http.HttpRequestOptions): Promise<http.HttpResp
}); });
} }
function decodeResponse(raw: any, encoding?: http.HttpResponseEncoding) { function decodeResponse(raw: any, encoding?: HttpResponseEncoding) {
let charsetName = "UTF-8"; let charsetName = "UTF-8";
if (encoding === http.HttpResponseEncoding.GBK) { if (encoding === HttpResponseEncoding.GBK) {
charsetName = 'GBK'; charsetName = 'GBK';
} }
return raw.toString(charsetName) return raw.toString(charsetName)
} }
export function addHeader(headers: Headers, key: string, value: string): void {
if (!headers[key]) {
headers[key] = value;
} else if (Array.isArray(headers[key])) {
(<string[]>headers[key]).push(value);
} else {
let values: string[] = [<string>headers[key]];
values.push(value);
headers[key] = values;
}
}

View File

@ -1,6 +1,7 @@
//@private //@private
declare module "http/http-request" { declare module "http/http-request" {
import * as http from "http"; import { HttpResponse, HttpRequestOptions, Headers } from "http";
export var request: (options: http.HttpRequestOptions) => Promise<http.HttpResponse>; export var request: (options: HttpRequestOptions) => Promise<HttpResponse>;
export function addHeader(headers: Headers, key: string, value: string): void;
} }

View File

@ -2,7 +2,7 @@
* iOS specific http request implementation. * iOS specific http request implementation.
*/ */
import * as http from "http"; import { HttpRequestOptions, HttpResponse, Headers } from "http";
import * as types from "utils/types"; import * as types from "utils/types";
import * as imageSourceModule from "image-source"; import * as imageSourceModule from "image-source";
@ -13,6 +13,11 @@ import getter = utils.ios.getter;
import * as domainDebugger from "./../debugger/debugger"; import * as domainDebugger from "./../debugger/debugger";
export const enum HttpResponseEncoding {
UTF8,
GBK
}
var device = utils.ios.getter(UIDevice, UIDevice.currentDevice).userInterfaceIdiom === UIUserInterfaceIdiom.Phone ? "Phone" : "Pad"; var device = utils.ios.getter(UIDevice, UIDevice.currentDevice).userInterfaceIdiom === UIUserInterfaceIdiom.Phone ? "Phone" : "Pad";
var GET = "GET"; var GET = "GET";
@ -59,8 +64,8 @@ function ensureImageSource() {
} }
} }
export function request(options: http.HttpRequestOptions): Promise<http.HttpResponse> { export function request(options: HttpRequestOptions): Promise<HttpResponse> {
return new Promise<http.HttpResponse>((resolve, reject) => { return new Promise<HttpResponse>((resolve, reject) => {
try { try {
var network = domainDebugger.getNetwork(); var network = domainDebugger.getNetwork();
@ -101,12 +106,12 @@ export function request(options: http.HttpRequestOptions): Promise<http.HttpResp
if (error) { if (error) {
reject(new Error(error.localizedDescription)); reject(new Error(error.localizedDescription));
} else { } else {
var headers: http.Headers = {}; var headers: Headers = {};
if (response && response.allHeaderFields) { if (response && response.allHeaderFields) {
var headerFields = response.allHeaderFields; var headerFields = response.allHeaderFields;
headerFields.enumerateKeysAndObjectsUsingBlock((key, value, stop) => { headerFields.enumerateKeysAndObjectsUsingBlock((key, value, stop) => {
(<any>http).addHeader(headers, key, value); addHeader(headers, key, value);
}); });
} }
@ -128,10 +133,8 @@ export function request(options: http.HttpRequestOptions): Promise<http.HttpResp
resolve({ resolve({
content: { content: {
raw: data, raw: data,
toString: (encoding?: http.HttpResponseEncoding) => { return NSDataToString(data, encoding); }, toString: (encoding?: any) => NSDataToString(data, encoding),
toJSON: (encoding?: http.HttpResponseEncoding) => { toJSON: (encoding?: any) => parseJSON(NSDataToString(data, encoding)),
return parseJSON(NSDataToString(data, encoding));
},
toImage: () => { toImage: () => {
ensureImageSource(); ensureImageSource();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -180,10 +183,22 @@ export function request(options: http.HttpRequestOptions): Promise<http.HttpResp
}); });
} }
function NSDataToString(data: any, encoding?: http.HttpResponseEncoding): string { function NSDataToString(data: any, encoding?: HttpResponseEncoding): string {
let code = 4; //UTF8 let code = 4; //UTF8
if (encoding === http.HttpResponseEncoding.GBK) { if (encoding === HttpResponseEncoding.GBK) {
code = 1586; code = 1586;
} }
return NSString.alloc().initWithDataEncoding(data, code).toString(); return NSString.alloc().initWithDataEncoding(data, code).toString();
} }
export function addHeader(headers: Headers, key: string, value: string): void {
if (!headers[key]) {
headers[key] = value;
} else if (Array.isArray(headers[key])) {
(<string[]>headers[key]).push(value);
} else {
let values: string[] = [<string>headers[key]];
values.push(value);
headers[key] = values;
}
}

View File

@ -122,6 +122,7 @@ declare module "http" {
UTF8, UTF8,
GBK GBK
} }
/** /**
* Encapsulates the content of an HttpResponse. * Encapsulates the content of an HttpResponse.
*/ */

View File

@ -1,6 +1,5 @@
import * as image from "image-source"; import * as image from "image-source";
import * as httpRequest from "http/http-request"; import * as httpRequest from "http/http-request";
import * as dts from "http";
global.moduleMerge(httpRequest, exports); global.moduleMerge(httpRequest, exports);
@ -50,16 +49,4 @@ export function getFile(arg: any, destinationFilePath?: string): Promise<any> {
} }
}, e => reject(e)); }, e => reject(e));
}); });
}
export function addHeader(headers: dts.Headers, key: string, value: string): void{
if(!headers[key]) {
headers[key] = value;
} else if (Array.isArray(headers[key])){
(<string[]>headers[key]).push(value);
} else {
let values: string[] = [<string>headers[key]];
values.push(value);
headers[key] = values;
}
} }

View File

@ -1,63 +0,0 @@
import * as utils from "utils/utils";
import * as httpModule from "http";
import * as imageAssetModule from "image-asset";
var http: typeof httpModule;
function ensureHttp() {
if (!http) {
http = require("http");
}
}
// This is used for definition purposes only, it does not generate JavaScript for it.
import * as definition from "image-source";
export function fromAsset(asset: imageAssetModule.ImageAsset): Promise<definition.ImageSource> {
let image = new definition.ImageSource();
return image.fromAsset(asset);
}
export function fromResource(name: string): definition.ImageSource {
var image = new definition.ImageSource();
return image.loadFromResource(name) ? image : null;
}
export function fromFile(path: string): definition.ImageSource {
var image = new definition.ImageSource();
return image.loadFromFile(path) ? image : null;
}
export function fromData(data: any): definition.ImageSource {
var image = new definition.ImageSource();
return image.loadFromData(data) ? image : null;
}
export function fromBase64(source: string): definition.ImageSource {
var image = new definition.ImageSource();
return image.loadFromBase64(source) ? image : null;
}
export function fromNativeSource(source: any): definition.ImageSource {
var image = new definition.ImageSource();
return image.setNativeSource(source) ? image : null;
}
export function fromUrl(url: string): Promise<definition.ImageSource> {
ensureHttp();
return http.getImage(url);
}
export function fromFileOrResource(path: string): definition.ImageSource {
if (!isFileOrResourcePath(path)) {
throw new Error("Path \"" + "\" is not a valid file or resource.");
}
if (path.indexOf(utils.RESOURCE_PREFIX) === 0) {
return fromResource(path.substr(utils.RESOURCE_PREFIX.length));
}
return fromFile(path);
}
export function isFileOrResourcePath(path: string): boolean {
return utils.isFileOrResourcePath(path);
}

View File

@ -1,11 +1,22 @@
import { ImageSource as ImageSourceDeifinition } from "image-source"; // Definitions.
import { ImageSource as ImageSourceDefinition } from "image-source";
export * from "./image-source-common"; import { ImageAsset } from "image-asset";
import * as fs from "file-system"; import * as httpModule from "http";
import * as imageAssetModule from "image-asset";
// Types.
import { path as fsPath, knownFolders } from "file-system";
import { isFileOrResourcePath, RESOURCE_PREFIX } from "utils/utils";
import { getNativeApplication } from "application"; import { getNativeApplication } from "application";
export { isFileOrResourcePath };
let http: typeof httpModule;
function ensureHttp() {
if (!http) {
http = require("http");
}
}
let application: android.app.Application; let application: android.app.Application;
let resources: android.content.res.Resources; let resources: android.content.res.Resources;
@ -24,11 +35,11 @@ function getResources() {
return resources; return resources;
} }
export class ImageSource implements ImageSourceDeifinition { export class ImageSource implements ImageSourceDefinition {
public android: android.graphics.Bitmap; public android: android.graphics.Bitmap;
public ios: UIImage; public ios: UIImage;
public fromAsset(asset: imageAssetModule.ImageAsset): Promise<ImageSource> { public fromAsset(asset: ImageAsset): Promise<ImageSource> {
return new Promise<ImageSource>((resolve, reject) => { return new Promise<ImageSource>((resolve, reject) => {
asset.getImageAsync((image, err) => { asset.getImageAsync((image, err) => {
if (image) { if (image) {
@ -87,7 +98,7 @@ export class ImageSource implements ImageSourceDeifinition {
public loadFromFile(path: string): boolean { public loadFromFile(path: string): boolean {
let fileName = typeof path === "string" ? path.trim() : ""; let fileName = typeof path === "string" ? path.trim() : "";
if (fileName.indexOf("~/") === 0) { if (fileName.indexOf("~/") === 0) {
fileName = fs.path.join(fs.knownFolders.currentApp().path, fileName.replace("~/", "")); fileName = fsPath.join(knownFolders.currentApp().path, fileName.replace("~/", ""));
} }
this.setRotationAngleFromFile(fileName); this.setRotationAngleFromFile(fileName);
@ -198,4 +209,50 @@ function getTargetFormat(format: "png" | "jpeg" | "jpg"): android.graphics.Bitma
default: default:
return android.graphics.Bitmap.CompressFormat.PNG; return android.graphics.Bitmap.CompressFormat.PNG;
} }
}
export function fromAsset(asset: ImageAsset): Promise<ImageSource> {
const image = new ImageSource();
return image.fromAsset(asset);
}
export function fromResource(name: string): ImageSource {
const image = new ImageSource();
return image.loadFromResource(name) ? image : null;
}
export function fromFile(path: string): ImageSource {
const image = new ImageSource();
return image.loadFromFile(path) ? image : null;
}
export function fromData(data: any): ImageSource {
const image = new ImageSource();
return image.loadFromData(data) ? image : null;
}
export function fromBase64(source: string): ImageSource {
const image = new ImageSource();
return image.loadFromBase64(source) ? image : null;
}
export function fromNativeSource(source: any): ImageSource {
const image = new ImageSource();
return image.setNativeSource(source) ? image : null;
}
export function fromUrl(url: string): Promise<ImageSource> {
ensureHttp();
return http.getImage(url);
}
export function fromFileOrResource(path: string): ImageSource {
if (!isFileOrResourcePath(path)) {
throw new Error("Path \"" + "\" is not a valid file or resource.");
}
if (path.indexOf(RESOURCE_PREFIX) === 0) {
return fromResource(path.substr(RESOURCE_PREFIX.length));
}
return fromFile(path);
} }

View File

@ -1,21 +1,30 @@
import * as definition from "image-source"; // Definitions.
import * as types from "utils/types"; import { ImageSource as ImageSourceDefinition } from "image-source";
import * as fs from "file-system"; import { ImageAsset } from "image-asset";
import * as common from "./image-source-common"; import * as httpModule from "http";
import * as enums from "ui/enums";
import * as imageAssetModule from "image-asset";
global.moduleMerge(common, exports); // Types.
import { path as fsPath, knownFolders } from "file-system";
import { isFileOrResourcePath, RESOURCE_PREFIX } from "utils/utils";
export class ImageSource implements definition.ImageSource { export { isFileOrResourcePath };
let http: typeof httpModule;
function ensureHttp() {
if (!http) {
http = require("http");
}
}
export class ImageSource implements ImageSourceDefinition {
public android: android.graphics.Bitmap; public android: android.graphics.Bitmap;
public ios: UIImage; public ios: UIImage;
public fromAsset(asset: imageAssetModule.ImageAsset) { public fromAsset(asset: ImageAsset) {
return new Promise<definition.ImageSource>((resolve, reject) => { return new Promise<ImageSource>((resolve, reject) => {
asset.getImageAsync((image, err) => { asset.getImageAsync((image, err) => {
if (image) { if (image) {
resolve(common.fromNativeSource(image)); resolve(fromNativeSource(image));
} }
else { else {
reject(err); reject(err);
@ -50,26 +59,14 @@ export class ImageSource implements definition.ImageSource {
} }
public loadFromFile(path: string): boolean { public loadFromFile(path: string): boolean {
var fileName = types.isString(path) ? path.trim() : ""; this.ios = UIImage.imageWithContentsOfFile(getFileName(path));
if (fileName.indexOf("~/") === 0) {
fileName = fs.path.join(fs.knownFolders.currentApp().path, fileName.replace("~/", ""));
}
this.ios = UIImage.imageWithContentsOfFile(fileName);
return this.ios != null; return this.ios != null;
} }
public fromFile(path: string): Promise<boolean> { public fromFile(path: string): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => { return new Promise<boolean>((resolve, reject) => {
try { try {
var fileName = types.isString(path) ? path.trim() : ""; (<any>UIImage).tns_decodeImageWidthContentsOfFileCompletion(getFileName(path), image => {
if (fileName.indexOf("~/") === 0) {
fileName = fs.path.join(fs.knownFolders.currentApp().path, fileName.replace("~/", ""));
}
(<any>UIImage).tns_decodeImageWidthContentsOfFileCompletion(fileName, image => {
this.ios = image; this.ios = image;
resolve(true); resolve(true);
}); });
@ -98,8 +95,8 @@ export class ImageSource implements definition.ImageSource {
} }
public loadFromBase64(source: string): boolean { public loadFromBase64(source: string): boolean {
if (types.isString(source)) { if (typeof source === "string") {
var data = NSData.alloc().initWithBase64EncodedStringOptions(source, NSDataBase64DecodingOptions.IgnoreUnknownCharacters); const data = NSData.alloc().initWithBase64EncodedStringOptions(source, NSDataBase64DecodingOptions.IgnoreUnknownCharacters);
this.ios = UIImage.imageWithData(data); this.ios = UIImage.imageWithData(data);
} }
@ -128,13 +125,12 @@ export class ImageSource implements definition.ImageSource {
return source != null; return source != null;
} }
public saveToFile(path: string, format: string, quality?: number): boolean { public saveToFile(path: string, format: "png" | "jpeg" | "jpg", quality?: number): boolean {
if (!this.ios) { if (!this.ios) {
return false; return false;
} }
var data = getImageData(this.ios, format, quality); const data = getImageData(this.ios, format, quality);
if (data) { if (data) {
return data.writeToFileAtomically(path, true); return data.writeToFileAtomically(path, true);
} }
@ -142,14 +138,13 @@ export class ImageSource implements definition.ImageSource {
return false; return false;
} }
public toBase64String(format: string, quality?: number): string { public toBase64String(format: "png" | "jpeg" | "jpg", quality?: number): string {
var res = null; let res = null;
if (!this.ios) { if (!this.ios) {
return res; return res;
} }
var data = getImageData(this.ios, format, quality); const data = getImageData(this.ios, format, quality);
if (data) { if (data) {
res = data.base64Encoding(); res = data.base64Encoding();
} }
@ -179,15 +174,69 @@ export class ImageSource implements definition.ImageSource {
} }
} }
function getImageData(instance: UIImage, format: string, quality = 1.0): NSData { function getFileName(path: string): string {
let fileName = typeof path === "string" ? path.trim() : "";
if (fileName.indexOf("~/") === 0) {
fileName = fsPath.join(knownFolders.currentApp().path, fileName.replace("~/", ""));
}
return fileName;
}
function getImageData(instance: UIImage, format: "png" | "jpeg" | "jpg", quality = 1.0): NSData {
var data = null; var data = null;
switch (format) { switch (format) {
case enums.ImageFormat.png: // PNG case "png": // PNG
data = UIImagePNGRepresentation(instance); data = UIImagePNGRepresentation(instance);
break; break;
case enums.ImageFormat.jpeg || enums.ImageFormat.jpg: // JPEG case "jpeg" || "jpg": // JPEG
data = UIImageJPEGRepresentation(instance, quality); data = UIImageJPEGRepresentation(instance, quality);
break; break;
} }
return data; return data;
}
export function fromAsset(asset: ImageAsset): Promise<ImageSource> {
const image = new ImageSource();
return image.fromAsset(asset);
}
export function fromResource(name: string): ImageSource {
const image = new ImageSource();
return image.loadFromResource(name) ? image : null;
}
export function fromFile(path: string): ImageSource {
const image = new ImageSource();
return image.loadFromFile(path) ? image : null;
}
export function fromData(data: any): ImageSource {
const image = new ImageSource();
return image.loadFromData(data) ? image : null;
}
export function fromBase64(source: string): ImageSource {
const image = new ImageSource();
return image.loadFromBase64(source) ? image : null;
}
export function fromNativeSource(source: any): ImageSource {
const image = new ImageSource();
return image.setNativeSource(source) ? image : null;
}
export function fromUrl(url: string): Promise<ImageSource> {
ensureHttp();
return http.getImage(url);
}
export function fromFileOrResource(path: string): ImageSource {
if (!isFileOrResourcePath(path)) {
throw new Error("Path \"" + "\" is not a valid file or resource.");
}
if (path.indexOf(RESOURCE_PREFIX) === 0) {
return fromResource(path.substr(RESOURCE_PREFIX.length));
}
return fromFile(path);
} }

View File

@ -28,7 +28,8 @@
/// <reference path="text/text.d.ts" /> /// <reference path="text/text.d.ts" />
/// <reference path="timer/timer.d.ts" /> /// <reference path="timer/timer.d.ts" />
/// <reference path="trace/trace.d.ts" /> /// <reference path="trace/trace.d.ts" />
/// <reference path="ui/definitions.d.ts" /> /// <reference path="ui/core/properties.d.ts" />
/// <reference path="ui/core/view-base.d.ts" />
/// <reference path="ui/action-bar/action-bar.d.ts" /> /// <reference path="ui/action-bar/action-bar.d.ts" />
/// <reference path="ui/activity-indicator/activity-indicator.d.ts" /> /// <reference path="ui/activity-indicator/activity-indicator.d.ts" />
/// <reference path="ui/animation/animation.d.ts" /> /// <reference path="ui/animation/animation.d.ts" />
@ -43,6 +44,7 @@
/// <reference path="ui/core/bindable.d.ts" /> /// <reference path="ui/core/bindable.d.ts" />
/// <reference path="ui/core/control-state-change.d.ts" /> /// <reference path="ui/core/control-state-change.d.ts" />
/// <reference path="ui/core/dependency-observable.d.ts" /> /// <reference path="ui/core/dependency-observable.d.ts" />
/// <reference path="ui/core/properties.d.ts" />
/// <reference path="ui/core/view.d.ts" /> /// <reference path="ui/core/view.d.ts" />
/// <reference path="ui/core/weak-event-listener.d.ts" /> /// <reference path="ui/core/weak-event-listener.d.ts" />
/// <reference path="ui/date-picker/date-picker.d.ts" /> /// <reference path="ui/date-picker/date-picker.d.ts" />
@ -78,6 +80,7 @@
/// <reference path="ui/styling/css-selector.d.ts" /> /// <reference path="ui/styling/css-selector.d.ts" />
/// <reference path="ui/styling/font.d.ts" /> /// <reference path="ui/styling/font.d.ts" />
/// <reference path="ui/styling/style-property.d.ts" /> /// <reference path="ui/styling/style-property.d.ts" />
/// <reference path="ui/styling/style-properties.d.ts" />
/// <reference path="ui/styling/style-scope.d.ts" /> /// <reference path="ui/styling/style-scope.d.ts" />
/// <reference path="ui/styling/style.d.ts" /> /// <reference path="ui/styling/style.d.ts" />
/// <reference path="ui/styling/styling.d.ts" /> /// <reference path="ui/styling/styling.d.ts" />
@ -96,4 +99,4 @@
/// <reference path="utils/lazy.d.ts" /> /// <reference path="utils/lazy.d.ts" />
/// <reference path="utils/types.d.ts" /> /// <reference path="utils/types.d.ts" />
/// <reference path="utils/utils.d.ts" /> /// <reference path="utils/utils.d.ts" />
/// <reference path="xml/xml.d.ts" /> /// <reference path="xml/xml.d.ts" />

View File

@ -2,13 +2,12 @@
ActionBar as ActionBarDefinition, ActionBar as ActionBarDefinition,
ActionItems as ActionItemsDefinition, ActionItems as ActionItemsDefinition,
ActionItem as ActionItemDefinition, ActionItem as ActionItemDefinition,
IOSActionItemSettings, AndroidActionItemSettings, AndroidActionBarSettings, NavigationButton, IOSActionItemSettings, AndroidActionItemSettings, AndroidActionBarSettings
NavigationButton
} from "ui/action-bar"; } from "ui/action-bar";
export * from "ui/core/view"; export * from "ui/core/view";
import { View, ViewBase, Property, unsetValue, horizontalAlignmentProperty, verticalAlignmentProperty, HorizontalAlignment, VerticalAlignment } from "ui/core/view"; import { View, ViewBase, Property, unsetValue, horizontalAlignmentProperty, verticalAlignmentProperty } from "ui/core/view";
export module knownCollections { export module knownCollections {
export var actionItems = "actionItems"; export var actionItems = "actionItems";
@ -63,8 +62,8 @@ export class ActionBarBase extends View implements ActionBarDefinition {
this._titleView = value; this._titleView = value;
if (this._titleView) { if (this._titleView) {
this._titleView.style[horizontalAlignmentProperty.cssName] = HorizontalAlignment.CENTER; this._titleView.style[horizontalAlignmentProperty.cssName] = "center";
this._titleView.style[verticalAlignmentProperty.cssName] = VerticalAlignment.MIDDLE; this._titleView.style[verticalAlignmentProperty.cssName] = "middle";
this._addView(this._titleView); this._addView(this._titleView);
} }
@ -108,18 +107,6 @@ export class ActionBarBase extends View implements ActionBarDefinition {
} }
} }
public _addChildFromBuilder(name: string, value: any) {
if (value instanceof NavigationButton) {
this.navigationButton = value;
}
else if (value instanceof ActionItemDefinition) {
this.actionItems.addItem(value);
}
else if (value instanceof View) {
this.titleView = value;
}
}
public eachChildView(callback: (child: View) => boolean) { public eachChildView(callback: (child: View) => boolean) {
const titleView = this.titleView; const titleView = this.titleView;
if (titleView) { if (titleView) {
@ -267,8 +254,8 @@ export class ActionItemBase extends ViewBase implements ActionItemDefinition {
if (this._actionView) { if (this._actionView) {
this._addView(this._actionView); this._addView(this._actionView);
this._actionView.style[horizontalAlignmentProperty.cssName] = HorizontalAlignment.CENTER; this._actionView.style[horizontalAlignmentProperty.cssName] = "center";
this._actionView.style[verticalAlignmentProperty.cssName] = VerticalAlignment.MIDDLE; this._actionView.style[verticalAlignmentProperty.cssName] = "middle";
} }
if (this._actionBar) { if (this._actionBar) {

View File

@ -99,7 +99,7 @@ export class AndroidActionBarSettings implements AndroidActionBarSettingsDefinit
} }
export class NavigationButton extends ActionItem { export class NavigationButton extends ActionItem {
//
} }
export class ActionBar extends ActionBarBase { export class ActionBar extends ActionBarBase {
@ -123,6 +123,18 @@ export class ActionBar extends ActionBarBase {
return this._toolbar; return this._toolbar;
} }
public _addChildFromBuilder(name: string, value: any) {
if (value instanceof NavigationButton) {
this.navigationButton = value;
}
else if (value instanceof ActionItem) {
this.actionItems.addItem(value);
}
else if (value instanceof View) {
this.titleView = value;
}
}
public _createNativeView() { public _createNativeView() {
initializeMenuItemClickListener(); initializeMenuItemClickListener();
this._toolbar = new android.support.v7.widget.Toolbar(this._context); this._toolbar = new android.support.v7.widget.Toolbar(this._context);

View File

@ -2,12 +2,12 @@
* Contains the action bar related classes. * Contains the action bar related classes.
*/ */
declare module "ui/action-bar" { declare module "ui/action-bar" {
import { EventData, ViewBase, View, AddArrayFromBuilder, AddChildFromBuilder } from "ui/core/view"; import { EventData, ViewBase, View } from "ui/core/view";
/** /**
* Provides an abstraction over the ActionBar (android) and NavigationBar (iOS). * Provides an abstraction over the ActionBar (android) and NavigationBar (iOS).
*/ */
export class ActionBar extends View implements AddArrayFromBuilder, AddChildFromBuilder { export class ActionBar extends View {
/** /**
* Gets or sets the action bar title. * Gets or sets the action bar title.
@ -42,9 +42,6 @@ declare module "ui/action-bar" {
//@private //@private
_isEmpty(): boolean; _isEmpty(): boolean;
//@endprivate //@endprivate
_addArrayFromBuilder(name: string, value: Array<any>): void;
_addChildFromBuilder(name: string, value: any): void;
} }
/** /**

View File

@ -1,7 +1,6 @@
import { IOSActionItemSettings, ActionItem as ActionItemDefinition } from "ui/action-bar"; import { IOSActionItemSettings, ActionItem as ActionItemDefinition } from "ui/action-bar";
import { ActionItemBase, ActionBarBase, isVisible, View, colorProperty, backgroundColorProperty, backgroundInternalProperty, layout } from "./action-bar-common"; import { ActionItemBase, ActionBarBase, isVisible, View, colorProperty, backgroundColorProperty, backgroundInternalProperty, layout, Color } from "./action-bar-common";
import { ImageSource, fromFileOrResource } from "image-source"; import { ImageSource, fromFileOrResource } from "image-source";
import { Color } from "color";
export * from "./action-bar-common"; export * from "./action-bar-common";
@ -60,6 +59,18 @@ export class ActionBar extends ActionBarBase {
return null; return null;
} }
public _addChildFromBuilder(name: string, value: any) {
if (value instanceof NavigationButton) {
this.navigationButton = value;
}
else if (value instanceof ActionItem) {
this.actionItems.addItem(value);
}
else if (value instanceof View) {
this.titleView = value;
}
}
public update() { public update() {
const page = this.page; const page = this.page;
// Page should be attached to frame to update the action bar. // Page should be attached to frame to update the action bar.

View File

@ -1,5 +1,4 @@
import { ActivityIndicatorBase, busyProperty, colorProperty } from "./activity-indicator-common"; import { ActivityIndicatorBase, busyProperty, colorProperty, Color } from "./activity-indicator-common";
import { Color } from "color";
export * from "./activity-indicator-common"; export * from "./activity-indicator-common";

View File

@ -1,16 +1,20 @@
import { // Definitions.
import {
CubicBezierAnimationCurve as CubicBezierAnimationCurveDefinition, CubicBezierAnimationCurve as CubicBezierAnimationCurveDefinition,
AnimationPromise as AnimationPromiseDefinition, AnimationPromise as AnimationPromiseDefinition,
Animation as AnimationBaseDefinition, Animation as AnimationBaseDefinition,
AnimationDefinition, AnimationDefinition,
Pair Pair
} from "ui/animation"; } from "ui/animation";
import { View } from "ui/core/view";
// Types.
import { Color } from "color";
import { isEnabled as traceEnabled, write as traceWrite, categories as traceCategories } from "trace";
export { Color, traceEnabled, traceWrite, traceCategories };
export { AnimationPromise } from "ui/animation"; export { AnimationPromise } from "ui/animation";
import { View, Color, traceEnabled, traceWrite, traceCategories } from "ui/core/view";
export * from "ui/core/view";
export module Properties { export module Properties {
export var opacity = "opacity"; export var opacity = "opacity";
export var backgroundColor = "backgroundColor"; export var backgroundColor = "backgroundColor";

View File

@ -1,10 +1,9 @@
import { AnimationDefinition } from "ui/animation"; import { AnimationDefinition } from "ui/animation";
import { AnimationBase, Properties, PropertyAnimation, CubicBezierAnimationCurve, AnimationPromise, Color, traceWrite, traceEnabled, traceCategories } from "./animation-common";
import { import {
AnimationBase, Properties, PropertyAnimation, CubicBezierAnimationCurve, AnimationPromise,
opacityProperty, backgroundColorProperty, rotateProperty, opacityProperty, backgroundColorProperty, rotateProperty,
translateXProperty, translateYProperty, translateXProperty, translateYProperty, scaleXProperty, scaleYProperty
scaleXProperty, scaleYProperty, Color, traceWrite, traceEnabled, traceCategories } from "ui/styling/style-properties";
} from "./animation-common";
import { CacheLayerType, layout } from "utils/utils"; import { CacheLayerType, layout } from "utils/utils";
import lazy from "utils/lazy"; import lazy from "utils/lazy";

View File

@ -1,9 +1,11 @@
import { AnimationDefinition } from "ui/animation"; import { AnimationDefinition } from "ui/animation";
import { View } from "ui/core/view";
import { AnimationBase, Properties, PropertyAnimation, CubicBezierAnimationCurve, AnimationPromise, traceWrite, traceEnabled, traceCategories } from "./animation-common";
import { import {
AnimationBase, Properties, PropertyAnimation, CubicBezierAnimationCurve, AnimationPromise, View, opacityProperty, backgroundColorProperty, rotateProperty, Length, opacityProperty, backgroundColorProperty, rotateProperty,
translateXProperty, translateYProperty, translateXProperty, translateYProperty, scaleXProperty, scaleYProperty
scaleXProperty, scaleYProperty, traceEnabled, traceWrite, traceCategories, Length } from "ui/styling/style-properties";
} from "./animation-common";
import { ios } from "utils/utils"; import { ios } from "utils/utils";

View File

@ -1,3 +1,4 @@
// Definitions.
import { import {
KeyframeDeclaration as KeyframeDeclarationDefinition, KeyframeDeclaration as KeyframeDeclarationDefinition,
KeyframeInfo as KeyframeInfoDefinition, KeyframeInfo as KeyframeInfoDefinition,
@ -5,19 +6,17 @@ import {
KeyframeAnimation as KeyframeAnimationDefinition KeyframeAnimation as KeyframeAnimationDefinition
} from "ui/animation/keyframe-animation"; } from "ui/animation/keyframe-animation";
import { import { View, Color } from "ui/core/view";
View,
backgroundColorProperty, // Types.
scaleXProperty, import { unsetValue } from "ui/core/properties";
scaleYProperty,
translateXProperty,
translateYProperty,
rotateProperty,
opacityProperty,
unsetValue,
Color
} from "ui/core/view";
import { Animation } from "ui/animation"; import { Animation } from "ui/animation";
import {
backgroundColorProperty,
scaleXProperty, scaleYProperty,
translateXProperty, translateYProperty,
rotateProperty, opacityProperty
} from "ui/styling/style-properties";
export class KeyframeDeclaration implements KeyframeDeclarationDefinition { export class KeyframeDeclaration implements KeyframeDeclarationDefinition {
public property: string; public property: string;

View File

@ -1,15 +1,20 @@
import { debug, ScopeError, SourceError, Source } from "utils/debug"; // Definitions.
import { LoadOptions } from "ui/builder";
import { View, ViewBase, Template, KeyedTemplate } from "ui/core/view";
// Types.
import { debug, ScopeError, SourceError, Source } from "utils/debug";
import * as xml from "xml"; import * as xml from "xml";
import { View, Template, KeyedTemplate } from "ui/core/view";
import { File, path, knownFolders } from "file-system"; import { File, path, knownFolders } from "file-system";
import { isString, isFunction, isDefined } from "utils/types"; import { isString, isDefined } from "utils/types";
import { ComponentModule, setPropertyValue, getComponentModule } from "ui/builder/component-builder"; import { ComponentModule, setPropertyValue, getComponentModule } from "ui/builder/component-builder";
import { platformNames, device } from "platform"; import { platformNames, device } from "platform";
import { LoadOptions } from "ui/builder";
import { Page } from "ui/page";
import { resolveFileName } from "file-system/file-name-resolver"; import { resolveFileName } from "file-system/file-name-resolver";
import * as traceModule from "trace"; import * as traceModule from "trace";
const ios = platformNames.ios.toLowerCase();
const android = platformNames.android.toLowerCase();
const defaultNameSpaceMatcher = /tns\.xsd$/i; const defaultNameSpaceMatcher = /tns\.xsd$/i;
var trace: typeof traceModule; var trace: typeof traceModule;
@ -20,22 +25,15 @@ function ensureTrace() {
} }
export function parse(value: string | Template, context: any): View { export function parse(value: string | Template, context: any): View {
if (isString(value)) { if (typeof value === "function") {
var viewToReturn: View;
if (context instanceof View) {
context = getExports(context);
}
var componentModule = parseInternal(<string>value, context);
if (componentModule) {
viewToReturn = componentModule.component;
}
return viewToReturn;
} else if (isFunction(value)) {
return (<Template>value)(); return (<Template>value)();
} else {
const exports = context ? getExports(context) : undefined;
const componentModule = parseInternal(value, exports);
if (componentModule) {
return componentModule.component;
}
return undefined;
} }
} }
@ -62,7 +60,7 @@ function parseInternal(value: string, context: any, uri?: string, moduleNamePath
return ui.rootComponentModule; return ui.rootComponentModule;
} }
function loadCustomComponent(componentPath: string, componentName?: string, attributes?: Object, context?: Object, parentPage?: Page): ComponentModule { function loadCustomComponent(componentPath: string, componentName?: string, attributes?: Object, context?: Object, parentPage?: View): ComponentModule {
if (!parentPage && context) { if (!parentPage && context) {
// Read the parent page that was passed down below // Read the parent page that was passed down below
// https://github.com/NativeScript/NativeScript/issues/1639 // https://github.com/NativeScript/NativeScript/issues/1639
@ -119,8 +117,8 @@ function loadCustomComponent(componentPath: string, componentName?: string, attr
// Add component CSS file if exists. // Add component CSS file if exists.
var cssFilePath = resolveFileName(fullComponentPathFilePathWithoutExt, "css"); var cssFilePath = resolveFileName(fullComponentPathFilePathWithoutExt, "css");
if (cssFilePath) { if (cssFilePath) {
if (parentPage) { if (parentPage && typeof (<any>parentPage).addCssFile === "function") {
parentPage.addCssFile(cssFilePath); (<any>parentPage).addCssFile(cssFilePath);
} else { } else {
ensureTrace(); ensureTrace();
@ -155,7 +153,7 @@ export function load(pathOrOptions: string | LoadOptions, context?: any): View {
return viewToReturn; return viewToReturn;
} }
export function loadPage(moduleNamePath: string, fileName: string, context?: any): Page { export function loadPage(moduleNamePath: string, fileName: string, context?: any): View {
var componentModule: ComponentModule; var componentModule: ComponentModule;
// Check if the XML file exists. // Check if the XML file exists.
@ -173,7 +171,7 @@ export function loadPage(moduleNamePath: string, fileName: string, context?: any
(<any>componentModule.component).exports = context; (<any>componentModule.component).exports = context;
} }
return (<Page>componentModule.component); return componentModule.component;
} }
function loadInternal(fileName: string, context?: any): ComponentModule { function loadInternal(fileName: string, context?: any): ComponentModule {
@ -197,14 +195,20 @@ function loadInternal(fileName: string, context?: any): ComponentModule {
return componentModule; return componentModule;
} }
function getExports(instance: View): any { function getExports(instance: ViewBase): any {
var parent = instance.parent; const isView = !!instance._domId;
if (!isView) {
return (<any>instance).exports || instance;
}
while (parent && (<any>parent).exports === undefined) { let exportObject = (<any>instance).exports;
let parent = instance.parent;
while (exportObject === undefined && parent) {
exportObject = (<any>parent).exports;
parent = parent.parent; parent = parent.parent;
} }
return parent ? (<any>parent).exports : undefined; return exportObject;
} }
namespace xml2ui { namespace xml2ui {
@ -316,8 +320,12 @@ namespace xml2ui {
} }
private static isPlatform(value: string): boolean { private static isPlatform(value: string): boolean {
return value && (value.toLowerCase() === platformNames.android.toLowerCase() if (value) {
|| value.toLowerCase() === platformNames.ios.toLowerCase()); const toLower = value.toLowerCase();
return toLower === android || toLower === ios;
}
return false;
} }
private static isCurentPlatform(value: string): boolean { private static isCurentPlatform(value: string): boolean {
@ -514,7 +522,7 @@ namespace xml2ui {
private context: any; private context: any;
private currentPage: Page; private currentRootView: View;
private parents = new Array<ComponentModule>(); private parents = new Array<ComponentModule>();
private complexProperties = new Array<ComponentParser.ComplexProperty>(); private complexProperties = new Array<ComponentParser.ComplexProperty>();
@ -575,7 +583,7 @@ namespace xml2ui {
if (args.prefix && args.namespace) { if (args.prefix && args.namespace) {
// Custom components // Custom components
componentModule = loadCustomComponent(args.namespace, args.elementName, args.attributes, this.context, this.currentPage); componentModule = loadCustomComponent(args.namespace, args.elementName, args.attributes, this.context, this.currentRootView);
} else { } else {
// Default components // Default components
let namespace = args.namespace; let namespace = args.namespace;
@ -599,11 +607,11 @@ namespace xml2ui {
// Set root component. // Set root component.
this.rootComponentModule = componentModule; this.rootComponentModule = componentModule;
if (this.rootComponentModule && this.rootComponentModule.component instanceof Page) { if (this.rootComponentModule) {
this.currentPage = <Page>this.rootComponentModule.component; this.currentRootView = this.rootComponentModule.component;
if ((<any>this.currentPage).exports) { if ((<any>this.currentRootView).exports) {
this.context = (<any>this.currentPage).exports; this.context = (<any>this.currentRootView).exports;
} }
} }
} }

View File

@ -1,12 +1,14 @@
import { isString, isDefined, isFunction } from "utils/types"; // Deifinitions.
import { Page } from "ui/page";
import { View, isEventOrGesture } from "ui/core/view";
import { ComponentModule } from "ui/builder/component-builder"; import { ComponentModule } from "ui/builder/component-builder";
import { View } from "ui/core/view";
// Types.
import { isEventOrGesture } from "ui/core/bindable";
import { File, path, knownFolders } from "file-system"; import { File, path, knownFolders } from "file-system";
import { getBindingOptions, bindingConstants } from "./binding-builder"; import { getBindingOptions, bindingConstants } from "./binding-builder";
import { resolveFileName } from "file-system/file-name-resolver"; import { resolveFileName } from "file-system/file-name-resolver";
import * as debugModule from "utils/debug"; import * as debugModule from "utils/debug";
import * as platformModule from "platform"; import * as platform from "platform";
const UI_PATH = "ui/"; const UI_PATH = "ui/";
const MODULES = { const MODULES = {
@ -22,13 +24,6 @@ const CODEFILE = "codeFile";
const CSSFILE = "cssFile"; const CSSFILE = "cssFile";
const IMPORT = "import"; const IMPORT = "import";
let platform: typeof platformModule;
function ensurePlatform() {
if (!platform) {
platform = require("platform");
}
}
export function getComponentModule(elementName: string, namespace: string, attributes: Object, exports: Object, moduleNamePath?: string): ComponentModule { export function getComponentModule(elementName: string, namespace: string, attributes: Object, exports: Object, moduleNamePath?: string): ComponentModule {
var instance: View; var instance: View;
var instanceModule: Object; var instanceModule: Object;
@ -88,7 +83,7 @@ export function getComponentModule(elementName: string, namespace: string, attri
(<any>instance).exports = exports; (<any>instance).exports = exports;
} }
if (instance instanceof Page) { // if (instance instanceof Page) {
if (attributes[CODEFILE]) { if (attributes[CODEFILE]) {
let codeFilePath = attributes[CODEFILE].trim(); let codeFilePath = attributes[CODEFILE].trim();
if (codeFilePath.indexOf("~/") === 0) { if (codeFilePath.indexOf("~/") === 0) {
@ -104,26 +99,26 @@ export function getComponentModule(elementName: string, namespace: string, attri
} }
} }
if (attributes[CSSFILE]) { if (attributes[CSSFILE] && typeof (<any>instance).addCssFile === "function") {
let cssFilePath = attributes[CSSFILE].trim(); let cssFilePath = attributes[CSSFILE].trim();
if (cssFilePath.indexOf("~/") === 0) { if (cssFilePath.indexOf("~/") === 0) {
cssFilePath = path.join(knownFolders.currentApp().path, cssFilePath.replace("~/", "")); cssFilePath = path.join(knownFolders.currentApp().path, cssFilePath.replace("~/", ""));
} }
if (File.exists(cssFilePath)) { if (File.exists(cssFilePath)) {
instance.addCssFile(cssFilePath); (<any>instance).addCssFile(cssFilePath);
cssApplied = true; cssApplied = true;
} else { } else {
throw new Error(`Css file with path "${cssFilePath}" cannot be found!`); throw new Error(`Css file with path "${cssFilePath}" cannot be found!`);
} }
} }
} // }
} }
if (instance instanceof Page) { if (typeof (<any>instance).addCssFile === "function") {//instance instanceof Page) {
if (moduleNamePath && !cssApplied) { if (moduleNamePath && !cssApplied) {
let cssFilePath = resolveFileName(moduleNamePath, "css"); let cssFilePath = resolveFileName(moduleNamePath, "css");
if (cssFilePath) { if (cssFilePath) {
instance.addCssFile(cssFilePath); (<any>instance).addCssFile(cssFilePath);
cssApplied = true; cssApplied = true;
} }
} }
@ -131,7 +126,7 @@ export function getComponentModule(elementName: string, namespace: string, attri
if (!cssApplied) { if (!cssApplied) {
// Called only to apply application css. // Called only to apply application css.
// If we have page css (through file or cssAttribute) we have appCss applied. // If we have page css (through file or cssAttribute) we have appCss applied.
instance._refreshCss(); (<any>instance)._refreshCss();
} }
} }
@ -143,8 +138,6 @@ export function getComponentModule(elementName: string, namespace: string, attri
if (attr.indexOf(":") !== -1) { if (attr.indexOf(":") !== -1) {
var platformName = attr.split(":")[0].trim(); var platformName = attr.split(":")[0].trim();
ensurePlatform();
if (platformName.toLowerCase() === platform.device.os.toLowerCase()) { if (platformName.toLowerCase() === platform.device.os.toLowerCase()) {
attr = attr.split(":")[1].trim(); attr = attr.split(":")[1].trim();
} else { } else {
@ -158,12 +151,12 @@ export function getComponentModule(elementName: string, namespace: string, attri
const subPropName = properties[properties.length - 1]; const subPropName = properties[properties.length - 1];
for (let i = 0; i < properties.length - 1; i++) { for (let i = 0; i < properties.length - 1; i++) {
if (isDefined(subObj)) { if (subObj !== undefined && subObj !== null) {
subObj = subObj[properties[i]]; subObj = subObj[properties[i]];
} }
} }
if (isDefined(subObj)) { if (subObj !== undefined && subObj !== null) {
setPropertyValue(subObj, instanceModule, exports, subPropName, attrValue); setPropertyValue(subObj, instanceModule, exports, subPropName, attrValue);
} }
} else { } else {
@ -193,11 +186,11 @@ export function setPropertyValue(instance: View, instanceModule: Object, exports
var handler = exports && exports[propertyValue]; var handler = exports && exports[propertyValue];
// Check if the handler is function and add it to the instance for specified event name. // Check if the handler is function and add it to the instance for specified event name.
if (isFunction(handler)) { if (typeof handler === "function") {
instance.on(propertyName, handler); instance.on(propertyName, handler);
} }
} }
else if (isKnownFunction(propertyName, instance) && isFunction(exports && exports[propertyValue])) { else if (isKnownFunction(propertyName, instance) && exports && typeof exports[propertyValue] === "function") {
instance[propertyName] = exports[propertyValue]; instance[propertyName] = exports[propertyValue];
} }
else { else {
@ -218,7 +211,7 @@ function getBindingExpressionFromAttribute(value: string): string {
function isBinding(value: any): boolean { function isBinding(value: any): boolean {
var isBinding; var isBinding;
if (isString(value)) { if (typeof value === "string") {
var str = value.trim(); var str = value.trim();
isBinding = str.indexOf("{{") === 0 && str.lastIndexOf("}}") === str.length - 2; isBinding = str.indexOf("{{") === 0 && str.lastIndexOf("}}") === str.length - 2;
} }

View File

@ -1,9 +1,10 @@
import { import {
ButtonBase, TouchGestureEventData, GestureTypes, TouchAction, ButtonBase, PseudoClassHandler,
PseudoClassHandler,
paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length, zIndexProperty paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length, zIndexProperty
} from "./button-common"; } from "./button-common";
import { TouchGestureEventData, GestureTypes, TouchAction } from "ui/gestures";
export * from "./button-common"; export * from "./button-common";
interface ClickListener { interface ClickListener {

View File

@ -1,5 +1,12 @@
declare module "ui/core/bindable" { declare module "ui/core/bindable" {
import { ViewBase } from "ui/core/view-base"; import { ViewBase } from "ui/core/view-base";
import { Observable, WrappedValue, PropertyChangeData, EventData } from "data/observable";
import { isEnabled as traceEnabled, write as traceWrite, categories as traceCategories, notifyEvent as traceNotifyEvent, messageType as traceMessageType, isCategorySet } from "trace";
export {
Observable, WrappedValue, PropertyChangeData, EventData,
traceEnabled, traceWrite, traceCategories, traceNotifyEvent, traceMessageType, isCategorySet
};
/** /**
* The options object used in the Bindable.bind method. * The options object used in the Bindable.bind method.
@ -47,4 +54,7 @@
public sourceIsBindingContext: boolean; public sourceIsBindingContext: boolean;
public updateTwoWay(value: any); public updateTwoWay(value: any);
} }
export function getEventOrGestureName(name: string): string;
export function isEventOrGesture(name: string, view: ViewBase): boolean;
} }

View File

@ -1,22 +1,29 @@
import { BindingOptions } from "ui/core/bindable"; import { BindingOptions } from "ui/core/bindable";
import { Observable, PropertyChangeData } from "data/observable"; import { ViewBase } from "ui/core/view-base";
import { unsetValue } from "ui/core/properties";
import { Observable, WrappedValue, PropertyChangeData, EventData } from "data/observable";
import { addWeakEventListener, removeWeakEventListener } from "ui/core/weak-event-listener"; import { addWeakEventListener, removeWeakEventListener } from "ui/core/weak-event-listener";
import types = require("utils/types"); import { bindingConstants, parentsRegex } from "../builder/binding-builder";
import bindingBuilder = require("../builder/binding-builder"); import { escapeRegexSymbols } from "utils/utils";
import { ViewBase, isEventOrGesture, unsetValue } from "ui/core/view-base"; import { isEnabled as traceEnabled, write as traceWrite, categories as traceCategories, notifyEvent as traceNotifyEvent, isCategorySet, messageType as traceMessageType } from "trace";
import * as types from "utils/types";
import * as application from "application"; import * as application from "application";
import * as polymerExpressions from "js-libs/polymer-expressions"; import * as polymerExpressions from "js-libs/polymer-expressions";
import * as utils from "utils/utils";
import { write as traceWrite, categories as traceCategories, messageType as traceMessageType } from "trace"; export {
Observable, WrappedValue, PropertyChangeData, EventData,
traceEnabled, traceWrite, traceCategories, traceNotifyEvent, traceMessageType, isCategorySet
};
let contextKey = "context"; const contextKey = "context";
// this regex is used to get parameters inside [] for example: // this regex is used to get parameters inside [] for example:
// from $parents['ListView'] will return 'ListView' // from $parents['ListView'] will return 'ListView'
// from $parents[1] will return 1 // from $parents[1] will return 1
let paramsRegex = /\[\s*(['"])*(\w*)\1\s*\]/; const paramsRegex = /\[\s*(['"])*(\w*)\1\s*\]/;
let bc = bindingBuilder.bindingConstants; const bc = bindingConstants;
const emptyArray = []; const emptyArray = [];
function getProperties(property: string): Array<string> { function getProperties(property: string): Array<string> {
@ -25,8 +32,8 @@ function getProperties(property: string): Array<string> {
// first replace all '$parents[..]' with a safe string // first replace all '$parents[..]' with a safe string
// second removes all ] since they are not important for property access and not needed // second removes all ] since they are not important for property access and not needed
// then split properties either on '.' or '[' // then split properties either on '.' or '['
let parentsMatches = property.match(bindingBuilder.parentsRegex); const parentsMatches = property.match(parentsRegex);
result = property.replace(bindingBuilder.parentsRegex, "parentsMatch") result = property.replace(parentsRegex, "parentsMatch")
.replace(/\]/g, "") .replace(/\]/g, "")
.split(/\.|\[/); .split(/\.|\[/);
@ -41,6 +48,35 @@ function getProperties(property: string): Array<string> {
return result; return result;
} }
export function getEventOrGestureName(name: string): string {
return name.indexOf("on") === 0 ? name.substr(2, name.length - 2) : name;
}
// NOTE: method fromString from "ui/gestures";
export function isGesture(eventOrGestureName: string): boolean {
let t = eventOrGestureName.trim().toLowerCase();
return t === "tap"
|| t === "doubletap"
|| t === "pinch"
|| t === "pan"
|| t === "swipe"
|| t === "rotation"
|| t === "longpress"
|| t === "touch";
}
// TODO: Make this instance function so that we dont need public statc tapEvent = "tap"
// in controls. They will just override this one and provide their own event support.
export function isEventOrGesture(name: string, view: ViewBase): boolean {
if (typeof name === "string") {
let eventOrGestureName = getEventOrGestureName(name);
let evt = `${eventOrGestureName}Event`;
return view.constructor && evt in view.constructor || isGesture(eventOrGestureName.toLowerCase());
}
return false;
}
export class Binding { export class Binding {
private source: WeakRef<Object>; private source: WeakRef<Object>;
// TODO: target should be hard reference! // TODO: target should be hard reference!
@ -82,8 +118,9 @@ export class Binding {
public loadedHandlerVisualTreeBinding(args) { public loadedHandlerVisualTreeBinding(args) {
let target = args.object; let target = args.object;
target.off("loaded", this.loadedHandlerVisualTreeBinding, this); target.off("loaded", this.loadedHandlerVisualTreeBinding, this);
if (!types.isNullOrUndefined(target.bindingContext)) { const context = target.bindingContext;
this.update(target.bindingContext); if (context !== undefined && context !== null) {
this.update(context);
} }
}; };
@ -262,7 +299,7 @@ export class Binding {
// text="{{ sourceProperty = $parents['ListView'].test, expression = $parents['ListView'].test + 2}}" // text="{{ sourceProperty = $parents['ListView'].test, expression = $parents['ListView'].test + 2}}"
// update expression will be '$newPropertyValue + 2' // update expression will be '$newPropertyValue + 2'
// then on expression execution the new value will be taken and target property will be updated with the value of the expression. // then on expression execution the new value will be taken and target property will be updated with the value of the expression.
let escapedSourceProperty = utils.escapeRegexSymbols(this.options.sourceProperty); let escapedSourceProperty = escapeRegexSymbols(this.options.sourceProperty);
let expRegex = new RegExp(escapedSourceProperty, 'g'); let expRegex = new RegExp(escapedSourceProperty, 'g');
let resultExp = this.options.expression.replace(expRegex, bc.newPropertyValueKey); let resultExp = this.options.expression.replace(expRegex, bc.newPropertyValueKey);
return resultExp; return resultExp;
@ -421,7 +458,7 @@ export class Binding {
} }
} }
let parentsArray = expression.match(bindingBuilder.parentsRegex); let parentsArray = expression.match(parentsRegex);
if (parentsArray) { if (parentsArray) {
for (let i = 0; i < parentsArray.length; i++) { for (let i = 0; i < parentsArray.length; i++) {
parentViewAndIndex = this.getParentView(this.target.get(), parentsArray[i]); parentViewAndIndex = this.getParentView(this.target.get(), parentsArray[i]);
@ -486,7 +523,7 @@ export class Binding {
} }
private getParentView(target: any, property: string): { view: ViewBase, index: number } { private getParentView(target: any, property: string): { view: ViewBase, index: number } {
if (!target || !(target instanceof ViewBase)) { if (!target) {
return { view: null, index: null }; return { view: null, index: null };
} }
@ -545,20 +582,17 @@ export class Binding {
this.updating = true; this.updating = true;
try { try {
const isView = optionsInstance instanceof ViewBase if (isEventOrGesture(options.property, <any>optionsInstance) &&
if (isView &&
isEventOrGesture(options.property, <any>optionsInstance) &&
types.isFunction(value)) { types.isFunction(value)) {
// calling off method with null as handler will remove all handlers for options.property event // calling off method with null as handler will remove all handlers for options.property event
optionsInstance.off(options.property, null, optionsInstance.bindingContext); optionsInstance.off(options.property, null, optionsInstance.bindingContext);
optionsInstance.on(options.property, value, optionsInstance.bindingContext); optionsInstance.on(options.property, value, optionsInstance.bindingContext);
} else if (!isView && optionsInstance instanceof Observable) { } else if (optionsInstance instanceof Observable) {
optionsInstance.set(options.property, value); optionsInstance.set(options.property, value);
} else { } else {
optionsInstance[options.property] = value; optionsInstance[options.property] = value;
} }
} } catch (ex) {
catch (ex) {
traceWrite("Binding error while setting property " + options.property + " of " + optionsInstance + ": " + ex, traceWrite("Binding error while setting property " + options.property + " of " + optionsInstance + ": " + ex,
traceCategories.Binding, traceCategories.Binding,
traceMessageType.error); traceMessageType.error);
@ -566,4 +600,4 @@ export class Binding {
this.updating = false; this.updating = false;
} }
} }

View File

@ -1,40 +1,114 @@
// declare module "ui/core/properties" { declare module "ui/core/properties" {
// import {ViewBase} from "ui/coew/viewbase"; import { ViewBase } from "ui/core/view-base";
// import {Style} from "ui/styling/style"; import { Style } from "ui/styling/style";
export { Style };
// interface PropertyOptions<T, U> { //@private
// name: string, export function _isSet(cssProperty: CssProperty<any, any>, instance: Style): boolean;
// defaultValue?: U, //@endprivate
// affectsLayout?: boolean,
// equalityComparer?: (x: U, y: U) => boolean,
// valueChanged?: (target: T, oldValue: U, newValue: U) => void,
// valueConverter?: (value: any) => U
// }
// interface CssPropertyOptions<T extends Style, U> extends PropertyOptions<T, U> { /**
// cssName: string; * Value specifing that Property should be set to its initial value.
// } */
export const unsetValue: any;
// class Property<T extends ViewBase, U> implements PropertyDescriptor { export interface PropertyOptions<T, U> {
// constructor(options: PropertyOptions<T, U>); readonly name: string;
readonly defaultValue?: U;
readonly affectsLayout?: boolean;
readonly equalityComparer?: (x: U, y: U) => boolean;
readonly valueChanged?: (target: T, oldValue: U, newValue: U) => void;
readonly valueConverter?: (value: string) => U;
}
// public native: symbol; export interface CoerciblePropertyOptions<T, U> extends PropertyOptions<T, U> {
// public register(cls: { prototype: T }): void; readonly coerceValue: (t: T, u: U) => U;
// } }
// class InheritedProperty<T extends ViewBase, U> extends Property<T, U> { export interface CssPropertyOptions<T extends Style, U> extends PropertyOptions<T, U> {
// constructor(options: PropertyOptions<T, U>); readonly cssName: string;
// } }
// class CssProperty<T extends Style, U> { export interface CssAnimationPropertyOptions<T, U> {
// constructor(options: CssPropertyOptions<T, U>); readonly name: string;
readonly cssName?: string;
readonly defaultValue?: U;
readonly equalityComparer?: (x: U, y: U) => boolean;
readonly valueChanged?: (target: T, oldValue: U, newValue: U) => void;
readonly valueConverter?: (value: string) => U;
}
// public native: symbol; export class CssAnimationProperty<T extends Style, U> {
// public cssName: string; constructor(options: CssAnimationPropertyOptions<T, U>);
// public register(cls: { prototype: T }): void;
// }
// class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U> { public readonly name: string;
// constructor(options: CssPropertyOptions<T, U>); public readonly cssName: string;
// } public readonly native: symbol;
// }
readonly keyframe: string;
public register(cls: { prototype: T }): void;
public _valueConverter?: (value: string) => any;
public static _getByCssName(name: string): CssAnimationProperty<any, any>;
}
export class Property<T extends ViewBase, U> implements TypedPropertyDescriptor<U> {
constructor(options: PropertyOptions<T, U>);
public readonly native: symbol;
public readonly defaultValue: U;
public register(cls: { prototype: T }): void;
public nativeValueChange(T, U): void;
}
export class CoercibleProperty<T extends ViewBase, U> extends Property<T, U> implements TypedPropertyDescriptor<U> {
constructor(options: CoerciblePropertyOptions<T, U>);
public readonly coerce: (target: T) => void;
}
export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> {
constructor(options: PropertyOptions<T, U>);
}
export class CssProperty<T extends Style, U> {
constructor(options: CssPropertyOptions<T, U>);
public readonly native: symbol;
public readonly name: string;
public readonly cssName: string;
public readonly defaultValue: U;
public register(cls: { prototype: T }): void;
}
export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U> {
constructor(options: CssPropertyOptions<T, U>);
}
export interface ShorthandPropertyOptions<P> {
readonly name: string,
readonly cssName: string;
readonly converter: (value: string | P) => [CssProperty<any, any>, any][],
readonly getter: (this: Style) => string | P
}
export class ShorthandProperty<T extends Style, P> {
constructor(options: ShorthandPropertyOptions<P>);
public readonly native: symbol;
public readonly name: string;
public readonly cssName: string;
public register(cls: { prototype: T }): void;
}
export function initNativeView(view: ViewBase): void;
export function resetNativeView(view: ViewBase): void;
export function resetCSSProperties(style: Style): void;
export function propagateInheritableProperties(view: ViewBase): void;
export function propagateInheritableCssProperties(style: Style): void;
export function makeValidator<T>(...values: T[]): (value: any) => value is T;
export function makeParser<T>(isValid: (value: any) => boolean): (value: any) => T;
}

View File

@ -1,7 +1,10 @@
import { WrappedValue } from "data/observable"; // Definitions.
import { ViewBase } from "./view-base";
import { Style } from "ui/styling/style";
import * as definitions from "ui/core/view-base"; import * as definitions from "ui/core/view-base";
import { ViewBase } from "./view-base";
// Types.
import { WrappedValue } from "data/observable";
import { Style } from "ui/styling/style";
export { Style }; export { Style };

View File

@ -1,22 +1,19 @@
declare module "ui/core/view-base" { declare module "ui/core/view-base" {
import { Observable, EventData } from "data/observable"; import { Property, InheritedProperty, Style } from "ui/core/properties";
import { Property, InheritedProperty } from "ui/core/properties"; import { BindingOptions, Observable } from "ui/core/bindable";
import { Binding, BindingOptions } from "ui/core/bindable";
import { Style } from "ui/styling/style";
import { SelectorCore } from "ui/styling/css-selector"; import { SelectorCore } from "ui/styling/css-selector";
import { isIOS, isAndroid } from "platform"; import { isIOS, isAndroid } from "platform";
import { fromString as gestureFromString } from "ui/gestures";
import { KeyframeAnimation } from "ui/animation/keyframe-animation"; import { KeyframeAnimation } from "ui/animation/keyframe-animation";
import { isEnabled as traceEnabled, write as traceWrite, categories as traceCategories, notifyEvent as traceNotifyEvent, isCategorySet } from "trace";
import { Page } from "ui/page"; import { Page } from "ui/page";
import { layout } from "utils/utils";
export { import { Color } from "color";
Observable, EventData, KeyframeAnimation,
Binding, BindingOptions, Style, isIOS, isAndroid, gestureFromString,
traceEnabled, traceWrite, traceCategories, traceNotifyEvent, isCategorySet
};
export { isIOS, isAndroid, layout, Color };
export * from "ui/core/properties"; export * from "ui/core/properties";
export * from "ui/core/bindable";
/** /**
* Iterates through all child views (via visual tree) and executes a function. * Iterates through all child views (via visual tree) and executes a function.
@ -44,6 +41,24 @@ declare module "ui/core/view-base" {
export function getViewById(view: ViewBase, id: string): ViewBase; export function getViewById(view: ViewBase, id: string): ViewBase;
export abstract class ViewBase extends Observable { export abstract class ViewBase extends Observable {
public effectiveMinWidth: number;
public effectiveMinHeight: number;
public effectiveWidth: number;
public effectiveHeight: number;
public effectiveMarginTop: number;
public effectiveMarginRight: number;
public effectiveMarginBottom: number;
public effectiveMarginLeft: number;
public effectivePaddingTop: number;
public effectivePaddingRight: number;
public effectivePaddingBottom: number;
public effectivePaddingLeft: number;
public effectiveBorderTopWidth: number;
public effectiveBorderRightWidth: number;
public effectiveBorderBottomWidth: number;
public effectiveBorderLeftWidth: number;
/** /**
* String value used when hooking to loaded event. * String value used when hooking to loaded event.
*/ */
@ -193,117 +208,10 @@ declare module "ui/core/view-base" {
export const idProperty: Property<ViewBase, string>; export const idProperty: Property<ViewBase, string>;
export const classNameProperty: Property<ViewBase, string>; export const classNameProperty: Property<ViewBase, string>;
export const bindingContextProperty: InheritedProperty<ViewBase, any>; export const bindingContextProperty: InheritedProperty<ViewBase, any>;
}
declare module "ui/core/properties" {
import { ViewBase } from "ui/core/view-base";
import { Style } from "ui/styling/style";
//@private
export function _isSet(cssProperty: CssProperty<any, any>, instance: Style): boolean;
//@endprivate
/** /**
* Value specifing that Property should be set to its initial value. * Converts string into boolean value.
* Throws error if value is not 'true' or 'false'.
*/ */
export const unsetValue: any; export function booleanConverter(v: string): boolean;
export interface PropertyOptions<T, U> {
readonly name: string;
readonly defaultValue?: U;
readonly affectsLayout?: boolean;
readonly equalityComparer?: (x: U, y: U) => boolean;
readonly valueChanged?: (target: T, oldValue: U, newValue: U) => void;
readonly valueConverter?: (value: string) => U;
}
export interface CoerciblePropertyOptions<T, U> extends PropertyOptions<T, U> {
readonly coerceValue: (t: T, u: U) => U;
}
export interface CssPropertyOptions<T extends Style, U> extends PropertyOptions<T, U> {
readonly cssName: string;
}
export interface CssAnimationPropertyOptions<T, U> {
readonly name: string;
readonly cssName?: string;
readonly defaultValue?: U;
readonly equalityComparer?: (x: U, y: U) => boolean;
readonly valueChanged?: (target: T, oldValue: U, newValue: U) => void;
readonly valueConverter?: (value: string) => U;
}
export class CssAnimationProperty<T extends Style, U> {
constructor(options: CssAnimationPropertyOptions<T, U>);
public readonly name: string;
public readonly cssName: string;
public readonly native: symbol;
readonly keyframe: string;
public register(cls: { prototype: T }): void;
public _valueConverter?: (value: string) => any;
public static _getByCssName(name: string): CssAnimationProperty<any, any>;
}
export class Property<T extends ViewBase, U> implements TypedPropertyDescriptor<U> {
constructor(options: PropertyOptions<T, U>);
public readonly native: symbol;
public readonly defaultValue: U;
public register(cls: { prototype: T }): void;
public nativeValueChange(T, U): void;
}
export class CoercibleProperty<T extends ViewBase, U> extends Property<T, U> implements TypedPropertyDescriptor<U> {
constructor(options: CoerciblePropertyOptions<T, U>);
public readonly coerce: (target: T) => void;
}
export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> {
constructor(options: PropertyOptions<T, U>);
}
export class CssProperty<T extends Style, U> {
constructor(options: CssPropertyOptions<T, U>);
public readonly native: symbol;
public readonly name: string;
public readonly cssName: string;
public readonly defaultValue: U;
public register(cls: { prototype: T }): void;
}
export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U> {
constructor(options: CssPropertyOptions<T, U>);
}
export interface ShorthandPropertyOptions<P> {
readonly name: string,
readonly cssName: string;
readonly converter: (value: string | P) => [CssProperty<any, any>, any][],
readonly getter: (this: Style) => string | P
}
export class ShorthandProperty<T extends Style, P> {
constructor(options: ShorthandPropertyOptions<P>);
public readonly native: symbol;
public readonly name: string;
public readonly cssName: string;
public register(cls: { prototype: T }): void;
}
export function initNativeView(view: ViewBase): void;
export function resetNativeView(view: ViewBase): void;
export function resetCSSProperties(style: Style): void;
export function propagateInheritableProperties(view: ViewBase): void;
export function propagateInheritableCssProperties(style: Style): void;
export function makeValidator<T>(...values: T[]): (value: any) => value is T;
export function makeParser<T>(isValid: (value: any) => boolean): (value: any) => T;
} }

View File

@ -1,19 +1,26 @@
// Definitions.
import { ViewBase as ViewBaseDefinition } from "ui/core/view-base"; import { ViewBase as ViewBaseDefinition } from "ui/core/view-base";
import { Observable, EventData, PropertyChangeData } from "data/observable"; import { Page } from "ui/page";
import { Property, InheritedProperty, Style, clearInheritedProperties, propagateInheritableProperties, propagateInheritableCssProperties, resetCSSProperties, initNativeView, resetNativeView } from "./properties";
import { Binding, BindingOptions } from "ui/core/bindable";
import { isIOS, isAndroid } from "platform";
import { fromString as gestureFromString } from "ui/gestures";
import { SelectorCore } from "ui/styling/css-selector"; import { SelectorCore } from "ui/styling/css-selector";
import { Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf } from "ui/layouts/flexbox-layout";
import { Length } from "../styling/style-properties";
import { KeyframeAnimation } from "ui/animation/keyframe-animation"; import { KeyframeAnimation } from "ui/animation/keyframe-animation";
import { isEnabled as traceEnabled, write as traceWrite, categories as traceCategories, notifyEvent as traceNotifyEvent, isCategorySet } from "trace"; // Types.
import { Property, InheritedProperty, Style, clearInheritedProperties, propagateInheritableProperties, propagateInheritableCssProperties, resetCSSProperties, initNativeView, resetNativeView } from "./properties";
import { Page } from "ui/page"; import { Binding, BindingOptions, Observable, WrappedValue, PropertyChangeData, traceEnabled, traceWrite, traceCategories, traceNotifyEvent } from "ui/core/bindable";
import { isIOS, isAndroid } from "platform";
import { layout } from "utils/utils";
// TODO: Remove this import! // TODO: Remove this import!
import * as types from "utils/types"; import * as types from "utils/types";
import { Color } from "color";
export { isIOS, isAndroid, layout, Color };
export * from "ui/core/bindable";
export * from "./properties";
import * as ssm from "ui/styling/style-scope"; import * as ssm from "ui/styling/style-scope";
let styleScopeModule: typeof ssm; let styleScopeModule: typeof ssm;
function ensureStyleScopeModule() { function ensureStyleScopeModule() {
@ -22,12 +29,6 @@ function ensureStyleScopeModule() {
} }
} }
export {
Observable, EventData, Binding, BindingOptions, isIOS, isAndroid,
gestureFromString, traceEnabled, traceWrite, traceCategories, traceNotifyEvent, isCategorySet
};
export * from "./properties";
let defaultBindingSource = {}; let defaultBindingSource = {};
export function getAncestor(view: ViewBaseDefinition, criterion: string | Function): ViewBaseDefinition { export function getAncestor(view: ViewBaseDefinition, criterion: string | Function): ViewBaseDefinition {
@ -47,24 +48,6 @@ export function getAncestor(view: ViewBaseDefinition, criterion: string | Functi
return null; return null;
} }
export function getEventOrGestureName(name: string): string {
return name.indexOf("on") === 0 ? name.substr(2, name.length - 2) : name;
}
// TODO: Make this instance function so that we dont need public statc tapEvent = "tap"
// in controls. They will just override this one and provide their own event support.
export function isEventOrGesture(name: string, view: ViewBaseDefinition): boolean {
if (typeof name === "string") {
let eventOrGestureName = getEventOrGestureName(name);
let evt = `${eventOrGestureName}Event`;
return view.constructor && evt in view.constructor ||
gestureFromString(eventOrGestureName.toLowerCase()) !== undefined;
}
return false;
}
export function getViewById(view: ViewBaseDefinition, id: string): ViewBaseDefinition { export function getViewById(view: ViewBaseDefinition, id: string): ViewBaseDefinition {
if (!view) { if (!view) {
return undefined; return undefined;
@ -106,9 +89,12 @@ export function eachDescendant(view: ViewBaseDefinition, callback: (child: ViewB
view.eachChild(localCallback); view.eachChild(localCallback);
} }
let viewIdCounter = 0; let viewIdCounter = 1;
export class ViewBase extends Observable implements ViewBaseDefinition { export class ViewBase extends Observable implements ViewBaseDefinition {
public static loadedEvent = "loaded";
public static unloadedEvent = "unloaded";
public recycleNativeView: boolean; public recycleNativeView: boolean;
private _style: Style; private _style: Style;
@ -131,6 +117,45 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
public _cssState: ssm.CssState; public _cssState: ssm.CssState;
public _styleScope: ssm.StyleScope; public _styleScope: ssm.StyleScope;
// Dynamic properties.
left: Length;
top: Length;
effectiveLeft: number;
effectiveTop: number;
dock: "left" | "top" | "right" | "bottom";
row: number;
col: number;
rowSpan: number;
colSpan: number;
order: Order;
flexGrow: FlexGrow;
flexShrink: FlexShrink;
flexWrapBefore: FlexWrapBefore;
alignSelf: AlignSelf;
_oldLeft: number;
_oldTop: number;
_oldRight: number;
_oldBottom: number;
public effectiveMinWidth: number;
public effectiveMinHeight: number;
public effectiveWidth: number;
public effectiveHeight: number;
public effectiveMarginTop: number;
public effectiveMarginRight: number;
public effectiveMarginBottom: number;
public effectiveMarginLeft: number;
public effectivePaddingTop: number;
public effectivePaddingRight: number;
public effectivePaddingBottom: number;
public effectivePaddingLeft: number;
public effectiveBorderTopWidth: number;
public effectiveBorderRightWidth: number;
public effectiveBorderBottomWidth: number;
public effectiveBorderLeftWidth: number;
constructor() { constructor() {
super(); super();
this._domId = viewIdCounter++; this._domId = viewIdCounter++;
@ -188,6 +213,12 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
return null; return null;
} }
// Overriden so we don't raise `poropertyChange`
// The property will raise its own event.
public set(name: string, value: any) {
this[name] = WrappedValue.unwrap(value);
}
public onLoaded() { public onLoaded() {
this._isLoaded = true; this._isLoaded = true;
this._loadEachChild(); this._loadEachChild();
@ -474,7 +505,7 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
if (this._context) { if (this._context) {
view._setupUI(this._context, atIndex); view._setupUI(this._context, atIndex);
} }
if (this._isLoaded) { if (this._isLoaded) {
view.onLoaded(); view.onLoaded();
} }
@ -682,6 +713,28 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
ViewBase.prototype.isCollapsed = false; ViewBase.prototype.isCollapsed = false;
ViewBase.prototype._oldLeft = 0;
ViewBase.prototype._oldTop = 0;
ViewBase.prototype._oldRight = 0;
ViewBase.prototype._oldBottom = 0;
ViewBase.prototype.effectiveMinWidth = 0;
ViewBase.prototype.effectiveMinHeight = 0;
ViewBase.prototype.effectiveWidth = 0;
ViewBase.prototype.effectiveHeight = 0;
ViewBase.prototype.effectiveMarginTop = 0;
ViewBase.prototype.effectiveMarginRight = 0;
ViewBase.prototype.effectiveMarginBottom = 0;
ViewBase.prototype.effectiveMarginLeft = 0;
ViewBase.prototype.effectivePaddingTop = 0;
ViewBase.prototype.effectivePaddingRight = 0;
ViewBase.prototype.effectivePaddingBottom = 0;
ViewBase.prototype.effectivePaddingLeft = 0;
ViewBase.prototype.effectiveBorderTopWidth = 0;
ViewBase.prototype.effectiveBorderRightWidth = 0;
ViewBase.prototype.effectiveBorderBottomWidth = 0;
ViewBase.prototype.effectiveBorderLeftWidth = 0;
export const bindingContextProperty = new InheritedProperty<ViewBase, any>({ name: "bindingContext" }); export const bindingContextProperty = new InheritedProperty<ViewBase, any>({ name: "bindingContext" });
bindingContextProperty.register(ViewBase); bindingContextProperty.register(ViewBase);
@ -709,4 +762,15 @@ function resetStyles(view: ViewBase): void {
} }
export const idProperty = new Property<ViewBase, string>({ name: "id", valueChanged: (view, oldValue, newValue) => resetStyles(view) }); export const idProperty = new Property<ViewBase, string>({ name: "id", valueChanged: (view, oldValue, newValue) => resetStyles(view) });
idProperty.register(ViewBase); idProperty.register(ViewBase);
export function booleanConverter(v: string): boolean {
let lowercase = (v + '').toLowerCase();
if (lowercase === "true") {
return true;
} else if (lowercase === "false") {
return false;
}
throw new Error(`Invalid boolean: ${v}`);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,23 @@
import { PercentLength, Point, CustomLayoutView as CustomLayoutViewDefinition } from "ui/core/view"; // Definitions.
import { ad as androidBackground } from "ui/styling/background"; import { Point, CustomLayoutView as CustomLayoutViewDefinition } from "ui/core/view";
import { GestureTypes, GestureEventData } from "ui/gestures";
// Types.
import { Background, ad as androidBackground } from "ui/styling/background";
import { import {
ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty, visibilityProperty, opacityProperty, ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty,
minWidthProperty, minHeightProperty, Length, traceEnabled, traceWrite, traceCategories, traceNotifyEvent
widthProperty, heightProperty, marginLeftProperty, marginTopProperty,
marginRightProperty, marginBottomProperty, horizontalAlignmentProperty, verticalAlignmentProperty,
rotateProperty, scaleXProperty, scaleYProperty,
translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty,
Background, GestureTypes, GestureEventData,
traceEnabled, traceWrite, traceCategories, traceNotifyEvent, Visibility, HorizontalAlignment, VerticalAlignment
} from "./view-common"; } from "./view-common";
import {
Length, PercentLength, Visibility, HorizontalAlignment, VerticalAlignment,
visibilityProperty, opacityProperty, horizontalAlignmentProperty, verticalAlignmentProperty,
minWidthProperty, minHeightProperty, widthProperty, heightProperty,
marginLeftProperty, marginTopProperty, marginRightProperty, marginBottomProperty,
rotateProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty,
zIndexProperty, backgroundInternalProperty
} from "ui/styling/style-properties";
export * from "./view-common"; export * from "./view-common";
const ANDROID = "_android"; const ANDROID = "_android";
@ -328,28 +335,28 @@ export class View extends ViewCommon {
let nativeVisibility = this.nativeView.getVisibility(); let nativeVisibility = this.nativeView.getVisibility();
switch (nativeVisibility) { switch (nativeVisibility) {
case android.view.View.VISIBLE: case android.view.View.VISIBLE:
return Visibility.VISIBLE; return "visible";
case android.view.View.INVISIBLE: case android.view.View.INVISIBLE:
return Visibility.HIDDEN; return "hidden";
case android.view.View.GONE: case android.view.View.GONE:
return Visibility.COLLAPSE; return "collapse";
default: default:
throw new Error(`Unsupported android.view.View visibility: ${nativeVisibility}. Currently supported values are android.view.View.VISIBLE, android.view.View.INVISIBLE, android.view.View.GONE.`); throw new Error(`Unsupported android.view.View visibility: ${nativeVisibility}. Currently supported values are android.view.View.VISIBLE, android.view.View.INVISIBLE, android.view.View.GONE.`);
} }
} }
set [visibilityProperty.native](value: Visibility) { set [visibilityProperty.native](value: Visibility) {
switch (value) { switch (value) {
case Visibility.VISIBLE: case "visible":
this.nativeView.setVisibility(android.view.View.VISIBLE); this.nativeView.setVisibility(android.view.View.VISIBLE);
break; break;
case Visibility.HIDDEN: case "hidden":
this.nativeView.setVisibility(android.view.View.INVISIBLE); this.nativeView.setVisibility(android.view.View.INVISIBLE);
break; break;
case Visibility.COLLAPSE: case "collapse":
this.nativeView.setVisibility(android.view.View.GONE); this.nativeView.setVisibility(android.view.View.GONE);
break; break;
default: default:
throw new Error(`Invalid visibility value: ${value}. Valid values are: "${Visibility.VISIBLE}", "${Visibility.HIDDEN}", "${Visibility.COLLAPSE}".`); throw new Error(`Invalid visibility value: ${value}. Valid values are: visible, hidden, collapse.`);
} }
} }
@ -448,6 +455,64 @@ export class View extends ViewCommon {
} }
} }
export class CustomLayoutView extends View implements CustomLayoutViewDefinition {
private _viewGroup: android.view.ViewGroup;
get android(): android.view.ViewGroup {
return this._viewGroup;
}
get _nativeView(): android.view.ViewGroup {
return this._viewGroup;
}
public _createNativeView() {
this._viewGroup = new org.nativescript.widgets.ContentLayout(this._context);
}
public _addViewToNativeVisualTree(child: ViewCommon, atIndex: number = -1): boolean {
super._addViewToNativeVisualTree(child);
if (this._nativeView && child.nativeView) {
if (traceEnabled()) {
traceWrite(`${this}.nativeView.addView(${child}.nativeView, ${atIndex})`, traceCategories.VisualTreeEvents);
}
this._nativeView.addView(child.nativeView, atIndex);
if (child instanceof View) {
this._updateNativeLayoutParams(child);
}
return true;
}
return false;
}
public _updateNativeLayoutParams(child: View): void {
this._setChildMinWidthNative(child);
this._setChildMinHeightNative(child);
}
public _setChildMinWidthNative(child: View): void {
child._minWidthNative = child.minWidth;
}
public _setChildMinHeightNative(child: View): void {
child._minHeightNative = child.minHeight;
}
public _removeViewFromNativeVisualTree(child: ViewCommon): void {
super._removeViewFromNativeVisualTree(child);
if (this._nativeView && child._nativeView) {
this._nativeView.removeView(child._nativeView);
if (traceEnabled()) {
traceWrite(`${this}._nativeView.removeView(${child}._nativeView)`, traceCategories.VisualTreeEvents);
traceNotifyEvent(child, "childInLayoutRemovedFromNativeVisualTree");
}
}
}
}
type NativeSetter = { (view: android.view.View, value: number): void }; type NativeSetter = { (view: android.view.View, value: number): void };
type NativeGetter = { (view: android.view.View): number }; type NativeGetter = { (view: android.view.View): number };
const percentNotSupported = (view: android.view.View, value: number) => { throw new Error("PercentLength is not supported."); }; const percentNotSupported = (view: android.view.View, value: number) => { throw new Error("PercentLength is not supported."); };
@ -458,7 +523,7 @@ interface NativePercentLengthPropertyOptions {
setPixels: NativeSetter; setPixels: NativeSetter;
setPercent?: NativeSetter setPercent?: NativeSetter
} }
function createNativePercentLengthProperty({key, auto = 0, getPixels, setPixels, setPercent = percentNotSupported}: NativePercentLengthPropertyOptions) { function createNativePercentLengthProperty({ key, auto = 0, getPixels, setPixels, setPercent = percentNotSupported }: NativePercentLengthPropertyOptions) {
Object.defineProperty(View.prototype, key, { Object.defineProperty(View.prototype, key, {
get: function (this: View): PercentLength { get: function (this: View): PercentLength {
const value = getPixels(this.nativeView); const value = getPixels(this.nativeView);
@ -540,62 +605,4 @@ createNativePercentLengthProperty({
key: "_minHeightNative", key: "_minHeightNative",
getPixels: org.nativescript.widgets.ViewHelper.getMinHeight, getPixels: org.nativescript.widgets.ViewHelper.getMinHeight,
setPixels: org.nativescript.widgets.ViewHelper.setMinHeight setPixels: org.nativescript.widgets.ViewHelper.setMinHeight
}); });
export class CustomLayoutView extends View implements CustomLayoutViewDefinition {
private _viewGroup: android.view.ViewGroup;
get android(): android.view.ViewGroup {
return this._viewGroup;
}
get _nativeView(): android.view.ViewGroup {
return this._viewGroup;
}
public _createNativeView() {
this._viewGroup = new org.nativescript.widgets.ContentLayout(this._context);
}
public _addViewToNativeVisualTree(child: ViewCommon, atIndex: number = -1): boolean {
super._addViewToNativeVisualTree(child);
if (this._nativeView && child.nativeView) {
if (traceEnabled()) {
traceWrite(`${this}.nativeView.addView(${child}.nativeView, ${atIndex})`, traceCategories.VisualTreeEvents);
}
this._nativeView.addView(child.nativeView, atIndex);
if (child instanceof View) {
this._updateNativeLayoutParams(child);
}
return true;
}
return false;
}
public _updateNativeLayoutParams(child: View): void {
this._setChildMinWidthNative(child);
this._setChildMinHeightNative(child);
}
public _setChildMinWidthNative(child: View): void {
child._minWidthNative = child.minWidth;
}
public _setChildMinHeightNative(child: View): void {
child._minHeightNative = child.minHeight;
}
public _removeViewFromNativeVisualTree(child: ViewCommon): void {
super._removeViewFromNativeVisualTree(child);
if (this._nativeView && child._nativeView) {
this._nativeView.removeView(child._nativeView);
if (traceEnabled()) {
traceWrite(`${this}._nativeView.removeView(${child}._nativeView)`, traceCategories.VisualTreeEvents);
traceNotifyEvent(child, "childInLayoutRemovedFromNativeVisualTree");
}
}
}
}

View File

@ -1,32 +1,11 @@
declare module "ui/core/view" { declare module "ui/core/view" {
import { GestureTypes, GesturesObserver, GestureEventData, TouchGestureEventData, TouchAction } from "ui/gestures"; import { ViewBase, Property, EventData, Color } from "ui/core/view-base";
import {
ViewBase, Property, CssProperty, CssAnimationProperty, InheritedCssProperty, Style, EventData, ShorthandProperty
} from "ui/core/view-base";
import { Background } from "ui/styling/background";
import { Font, FontWeight, FontStyle } from "ui/styling/font";
import { Color } from "color";
export {
GestureTypes, GesturesObserver, GestureEventData, TouchGestureEventData, TouchAction,
Background, Font, Color
}
import { Animation, AnimationDefinition, AnimationPromise } from "ui/animation"; import { Animation, AnimationDefinition, AnimationPromise } from "ui/animation";
import { HorizontalAlignment, VerticalAlignment, Visibility, Length, PercentLength } from "ui/styling/style-properties";
import { GestureTypes, GestureEventData, GesturesObserver } from "ui/gestures";
export * from "ui/core/view-base"; export * from "ui/core/view-base";
export * from "ui/styling/style-properties";
export const zeroLength: Length;
/**
* Converts string into boolean value.
* Throws error if value is not 'true' or 'false'.
*/
export function booleanConverter(v: string): boolean;
/**
* Compares two Length objects.
*/
export function lengthComparer(x: Length, y: Length): boolean;
export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator; export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator;
@ -62,43 +41,6 @@ declare module "ui/core/view" {
height: number; height: number;
} }
export type Length = "auto" | number | {
readonly unit: "dip" | "px";
readonly value: number;
}
export namespace Length {
export function parse(text: string): Length;
export function equals(a: Length, b: Length): boolean;
/**
* Converts Length unit to device pixels.
* @param length The Length to convert.
* @param auto Value to use for conversion of "auto".
*/
export function toDevicePixels(length: Length, auto: number): number;
export function convertToString(length: Length): string;
}
export type PercentLength = "auto" | number | {
readonly unit: "%" | "dip" | "px";
/**
* Length value. When unit is "%" the value is normalized (ex. for 5% the value is 0.05)
*/
readonly value: number;
}
export namespace PercentLength {
export function parse(text: string): PercentLength;
export function equals(a: PercentLength, b: PercentLength): boolean;
/**
* Converts PercentLength unit to device pixels.
* @param length The PercentLength to convert.
* @param auto Value to use for conversion of "auto".
* @param parentAvailableWidth Value to use as base when converting percent unit.
*/
export function toDevicePixels(length: PercentLength, auto: number, parentAvailableWidth: number): number;
export function convertToString(length: PercentLength): string;
}
/** /**
* This class is the base class for all UI components. * This class is the base class for all UI components.
* A View occupies a rectangular area on the screen and is responsible for drawing and layouting of all UI components within. * A View occupies a rectangular area on the screen and is responsible for drawing and layouting of all UI components within.
@ -564,23 +506,6 @@ declare module "ui/core/view" {
_minHeightNative: Length; _minHeightNative: Length;
//@endprivate //@endprivate
public effectiveMinWidth: number;
public effectiveMinHeight: number;
public effectiveWidth: number;
public effectiveHeight: number;
public effectiveMarginTop: number;
public effectiveMarginRight: number;
public effectiveMarginBottom: number;
public effectiveMarginLeft: number;
public effectivePaddingTop: number;
public effectivePaddingRight: number;
public effectivePaddingBottom: number;
public effectivePaddingLeft: number;
public effectiveBorderTopWidth: number;
public effectiveBorderRightWidth: number;
public effectiveBorderBottomWidth: number;
public effectiveBorderLeftWidth: number;
/** /**
* __Obsolete:__ There is a new property system that does not rely on _getValue. * __Obsolete:__ There is a new property system that does not rely on _getValue.
*/ */
@ -668,131 +593,9 @@ declare module "ui/core/view" {
_applyXmlAttribute(attributeName: string, attrValue: any): boolean; _applyXmlAttribute(attributeName: string, attrValue: any): boolean;
} }
export namespace layout {
export const UNSPECIFIED: number;
export const EXACTLY: number;
export const AT_MOST: number;
export const MEASURED_HEIGHT_STATE_SHIFT: number;
export const MEASURED_STATE_TOO_SMALL: number;
export const MEASURED_STATE_MASK: number;
export const MEASURED_SIZE_MASK: number;
export function getMeasureSpecMode(spec: number): number;
export function getMeasureSpecSize(spec: number): number;
export function getDisplayDensity(): number;
export function makeMeasureSpec(size: number, mode: number): number;
export function toDevicePixels(value: number): number;
export function toDeviceIndependentPixels(value: number): number;
export function measureSpecToString(measureSpec: number): string;
}
export const automationTextProperty: Property<View, string>; export const automationTextProperty: Property<View, string>;
export const originXProperty: Property<View, number>; export const originXProperty: Property<View, number>;
export const originYProperty: Property<View, number>; export const originYProperty: Property<View, number>;
export const isEnabledProperty: Property<View, boolean>; export const isEnabledProperty: Property<View, boolean>;
export const isUserInteractionEnabledProperty: Property<View, boolean>; export const isUserInteractionEnabledProperty: Property<View, boolean>;
export const rotateProperty: CssAnimationProperty<Style, number>;
export const scaleXProperty: CssAnimationProperty<Style, number>;
export const scaleYProperty: CssAnimationProperty<Style, number>;
export const translateXProperty: CssAnimationProperty<Style, Length>;
export const translateYProperty: CssAnimationProperty<Style, Length>;
export const clipPathProperty: CssProperty<Style, string>;
export const colorProperty: InheritedCssProperty<Style, Color>;
export const backgroundColorProperty: CssAnimationProperty<Style, Color>;
export const backgroundImageProperty: CssProperty<Style, string>;
export const backgroundRepeatProperty: CssProperty<Style, BackgroundRepeat>;
export const backgroundSizeProperty: CssProperty<Style, string>;
export const backgroundPositionProperty: CssProperty<Style, string>;
export const borderColorProperty: ShorthandProperty<Style, string | Color>;
export const borderTopColorProperty: CssProperty<Style, Color>;
export const borderRightColorProperty: CssProperty<Style, Color>;
export const borderBottomColorProperty: CssProperty<Style, Color>;
export const borderLeftColorProperty: CssProperty<Style, Color>;
export const borderWidthProperty: ShorthandProperty<Style, string | Length>;
export const borderTopWidthProperty: CssProperty<Style, Length>;
export const borderRightWidthProperty: CssProperty<Style, Length>;
export const borderBottomWidthProperty: CssProperty<Style, Length>;
export const borderLeftWidthProperty: CssProperty<Style, Length>;
export const borderRadiusProperty: ShorthandProperty<Style, string | Length>;
export const borderTopLeftRadiusProperty: CssProperty<Style, Length>;
export const borderTopRightRadiusProperty: CssProperty<Style, Length>;
export const borderBottomRightRadiusProperty: CssProperty<Style, Length>;
export const borderBottomLeftRadiusProperty: CssProperty<Style, Length>;
export const zIndexProperty: CssProperty<Style, number>;
export const visibilityProperty: CssProperty<Style, Visibility>;
export const opacityProperty: CssAnimationProperty<Style, number>;
export const minWidthProperty: CssProperty<Style, Length>;
export const minHeightProperty: CssProperty<Style, Length>;
export const widthProperty: CssProperty<Style, Length>;
export const heightProperty: CssProperty<Style, Length>;
export const marginProperty: ShorthandProperty<Style, string | PercentLength>;
export const marginLeftProperty: CssProperty<Style, PercentLength>;
export const marginRightProperty: CssProperty<Style, PercentLength>;
export const marginTopProperty: CssProperty<Style, PercentLength>;
export const marginBottomProperty: CssProperty<Style, PercentLength>;
export const paddingProperty: ShorthandProperty<Style, string | Length>;
export const paddingLeftProperty: CssProperty<Style, Length>;
export const paddingRightProperty: CssProperty<Style, Length>;
export const paddingTopProperty: CssProperty<Style, Length>;
export const paddingBottomProperty: CssProperty<Style, Length>;
export const horizontalAlignmentProperty: CssProperty<Style, HorizontalAlignment>;
export const verticalAlignmentProperty: CssProperty<Style, VerticalAlignment>;
export const fontSizeProperty: InheritedCssProperty<Style, number>;
export const fontFamilyProperty: InheritedCssProperty<Style, string>;
export const fontStyleProperty: InheritedCssProperty<Style, FontStyle>;
export const fontWeightProperty: InheritedCssProperty<Style, FontWeight>;
export const backgroundInternalProperty: CssProperty<Style, Background>;
export const fontInternalProperty: InheritedCssProperty<Style, Font>;
export type BackgroundRepeat = "repeat" | "repeat-x" | "repeat-y" | "no-repeat";
export namespace BackgroundRepeat {
export const REPEAT: "repeat";
export const REPEAT_X: "repeat-x";
export const REPEAT_Y: "repeat-y";
export const NO_REPEAT: "no-repeat";
export function isValid(value: any): boolean;
export function parse(value: string): BackgroundRepeat;
}
export type Visibility = "visible" | "hidden" | "collapse";
export namespace Visibility {
export const VISIBLE: "visible";
export const HIDDEN: "hidden";
export const COLLAPSE: "collapse";
export function isValid(value: any): boolean;
export function parse(value: string): Visibility;
}
export type HorizontalAlignment = "left" | "center" | "right" | "stretch";
export namespace HorizontalAlignment {
export const LEFT: "left";
export const CENTER: "center";
export const RIGHT: "right";
export const STRETCH: "stretch";
export function isValid(value: any): boolean;
export function parse(value: string): HorizontalAlignment;
}
export type VerticalAlignment = "top" | "middle" | "bottom" | "stretch";
export namespace VerticalAlignment {
export const TOP: "top";
export const MIDDLE: "middle";
export const BOTTOM: "bottom";
export const STRETCH: "stretch";
export function isValid(value: any): boolean;
export function parse(value: string): VerticalAlignment;
}
} }

View File

@ -1,12 +1,20 @@
import { Point, View as ViewDefinition } from "ui/core/view"; // Definitions.
import { ios } from "ui/styling/background"; import { Point, View as ViewDefinition } from "ui/core/view";
import { ios, Background } from "ui/styling/background";
import { import {
ViewCommon, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty, visibilityProperty, opacityProperty, ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty,
rotateProperty, scaleXProperty, scaleYProperty, traceEnabled, traceWrite, traceCategories
translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty,
clipPathProperty, layout, traceEnabled, traceWrite, traceCategories, Background, Visibility, Length
} from "./view-common"; } from "./view-common";
import {
Visibility, Length,
visibilityProperty, opacityProperty,
rotateProperty, scaleXProperty, scaleYProperty,
translateXProperty, translateYProperty, zIndexProperty,
backgroundInternalProperty, clipPathProperty
} from "ui/styling/style-properties";
export * from "./view-common"; export * from "./view-common";
const PFLAG_FORCE_LAYOUT = 1; const PFLAG_FORCE_LAYOUT = 1;
@ -459,4 +467,4 @@ export class CustomLayoutView extends View {
child.nativeView.removeFromSuperview(); child.nativeView.removeFromSuperview();
} }
} }
} }

View File

@ -1,10 +1,8 @@
import { import {
DatePickerBase, yearProperty, monthProperty, dayProperty, DatePickerBase, yearProperty, monthProperty, dayProperty,
dateProperty, maxDateProperty, minDateProperty, colorProperty dateProperty, maxDateProperty, minDateProperty, colorProperty, Color
} from "./date-picker-common"; } from "./date-picker-common";
import { Color } from "color";
import { ios } from "utils/utils"; import { ios } from "utils/utils";
export * from "./date-picker-common"; export * from "./date-picker-common";
@ -87,12 +85,12 @@ export class DatePicker extends DatePickerBase {
picker.minimumDate = <any>nsDate; picker.minimumDate = <any>nsDate;
} }
get [colorProperty.native](): Color { get [colorProperty.native](): UIColor {
return ios.getColor(this.nativeView.valueForKey("textColor")); return this.nativeView.valueForKey("textColor");
} }
set [colorProperty.native](value: Color) { set [colorProperty.native](value: Color | UIColor) {
let picker = this.nativeView; let picker = this.nativeView;
picker.setValueForKey(value.ios, "textColor"); picker.setValueForKey(value instanceof Color ? value.ios : value, "textColor");
} }
} }

View File

@ -1,9 +1,8 @@
import { topmost } from "ui/frame"; // Deifinitions.
import { View } from "ui/core/view";
import { Color } from "color";
import { Page } from "ui/page"; import { Page } from "ui/page";
import { Button } from "ui/button"; import * as frameModule from "ui/frame";
import { TextField } from "ui/text-field";
import { Label } from "ui/label";
import { View, Color } from "ui/core/view";
export const STRING = "string"; export const STRING = "string";
export const PROMPT = "Prompt"; export const PROMPT = "Prompt";
@ -28,12 +27,17 @@ export module inputType {
export const password: string = "password"; export const password: string = "password";
} }
let frame: typeof frameModule;
export function getCurrentPage(): Page { export function getCurrentPage(): Page {
let topmostFrame = topmost(); if (!frame) {
frame = require("ui/frame");
}
let topmostFrame = frame.topmost();
if (topmostFrame) { if (topmostFrame) {
return topmostFrame.currentPage; return topmostFrame.currentPage;
} }
return undefined; return undefined;
} }
@ -48,26 +52,30 @@ function applySelectors(view: View) {
} }
let buttonColor: Color; let buttonColor: Color;
let buttonBackgroundColor: Color;
function getButtonColors(): void {
const Button = require("ui/button").Button;
const btn = new Button();
applySelectors(btn);
buttonColor = btn.color;
buttonBackgroundColor = btn.backgroundColor;
btn.onUnloaded();
}
// NOTE: This will fail if app.css is changed. // NOTE: This will fail if app.css is changed.
export function getButtonColor(): Color { export function getButtonColor(): Color {
if (!buttonColor) { if (!buttonColor) {
let btn = new Button(); getButtonColors();
applySelectors(btn);
buttonColor = btn.color;
btn.onUnloaded();
} }
return buttonColor; return buttonColor;
} }
let buttonBackgroundColor: Color;
// NOTE: This will fail if app.css is changed. // NOTE: This will fail if app.css is changed.
export function getButtonBackgroundColor(): Color { export function getButtonBackgroundColor(): Color {
if (!buttonBackgroundColor) { if (!buttonBackgroundColor) {
let btn = new Button(); getButtonColors();
applySelectors(btn);
buttonBackgroundColor = btn.backgroundColor;
btn.onUnloaded();
} }
return buttonBackgroundColor; return buttonBackgroundColor;
@ -76,7 +84,8 @@ export function getButtonBackgroundColor(): Color {
let textFieldColor: Color; let textFieldColor: Color;
export function getTextFieldColor(): Color { export function getTextFieldColor(): Color {
if (!textFieldColor) { if (!textFieldColor) {
let tf = new TextField(); const TextField = require("ui/text-field").TextField;
const tf = new TextField();
applySelectors(tf); applySelectors(tf);
textFieldColor = tf.color; textFieldColor = tf.color;
tf.onUnloaded(); tf.onUnloaded();
@ -89,6 +98,7 @@ let labelColor: Color;
// NOTE: This will fail if app.css is changed. // NOTE: This will fail if app.css is changed.
export function getLabelColor(): Color { export function getLabelColor(): Color {
if (!labelColor) { if (!labelColor) {
const Label = require("ui/label").Label;
let lbl = new Label(); let lbl = new Label();
applySelectors(lbl); applySelectors(lbl);
labelColor = lbl.color; labelColor = lbl.color;

View File

@ -1,12 +1,17 @@
import { Frame as FrameDefinition, NavigationEntry, BackstackEntry, NavigationTransition } from "ui/frame"; // Definitions.
import { Page, View, CustomLayoutView, isIOS, isAndroid, traceEnabled, traceWrite, traceCategories, EventData } from "ui/page"; import { Frame as FrameDefinition, NavigationEntry, BackstackEntry, NavigationTransition } from "ui/frame";
import { isString, isFunction, isDefined } from "utils/types"; import { Page } from "ui/page";
// Types.
import { View, CustomLayoutView, isIOS, isAndroid, traceEnabled, traceWrite, traceCategories, EventData } from "ui/core/view";
import { resolveFileName } from "file-system/file-name-resolver"; import { resolveFileName } from "file-system/file-name-resolver";
import * as fs from "file-system"; import { knownFolders, path } from "file-system";
import * as builder from "ui/builder"; import { parse, loadPage } from "ui/builder";
import * as application from "application"; import * as application from "application";
export * from "ui/page"; export { application };
export * from "ui/core/view";
function onLivesync(args: EventData): void { function onLivesync(args: EventData): void {
// give time to allow fileNameResolver & css to reload. // give time to allow fileNameResolver & css to reload.
@ -22,7 +27,7 @@ function onLivesync(args: EventData): void {
reloadPage(); reloadPage();
} catch (ex) { } catch (ex) {
// Show the error as modal page, save reference to the page in global context. // Show the error as modal page, save reference to the page in global context.
g.errorPage = builder.parse(`<Page><ScrollView><Label text="${ex}" textWrap="true" style="color: red;" /></ScrollView></Page>`); g.errorPage = parse(`<Page><ScrollView><Label text="${ex}" textWrap="true" style="color: red;" /></ScrollView></Page>`);
g.errorPage.showModal(); g.errorPage.showModal();
} }
}); });
@ -33,13 +38,11 @@ let frameStack: Array<FrameBase> = [];
function buildEntryFromArgs(arg: any): NavigationEntry { function buildEntryFromArgs(arg: any): NavigationEntry {
let entry: NavigationEntry; let entry: NavigationEntry;
if (arg instanceof Page) { if (typeof arg === "string") {
throw new Error("Navigating to a Page instance is no longer supported. Please navigate by using either a module name or a page factory function.");
} else if (isString(arg)) {
entry = { entry = {
moduleName: arg moduleName: arg
}; };
} else if (isFunction(arg)) { } else if (typeof arg === "function") {
entry = { entry = {
create: arg create: arg
} }
@ -77,15 +80,15 @@ export function resolvePageFromEntry(entry: NavigationEntry): Page {
if (entry.create) { if (entry.create) {
page = entry.create(); page = entry.create();
if (!(page && page instanceof Page)) { if (!page) {
throw new Error("Failed to create Page with entry.create() function."); throw new Error("Failed to create Page with entry.create() function.");
} }
} }
else if (entry.moduleName) { else if (entry.moduleName) {
// Current app full path. // Current app full path.
let currentAppPath = fs.knownFolders.currentApp().path; let currentAppPath = knownFolders.currentApp().path;
//Full path of the module = current app full path + module name. //Full path of the module = current app full path + module name.
let moduleNamePath = fs.path.join(currentAppPath, entry.moduleName); let moduleNamePath = path.join(currentAppPath, entry.moduleName);
let moduleExports; let moduleExports;
// web-pack case where developers register their page JS file manually. // web-pack case where developers register their page JS file manually.
@ -123,7 +126,7 @@ export function resolvePageFromEntry(entry: NavigationEntry): Page {
page = pageFromBuilder(moduleNamePath, moduleExports); page = pageFromBuilder(moduleNamePath, moduleExports);
} }
if (!(page && page instanceof Page)) { if (!page) {
throw new Error("Failed to load Page from entry.moduleName: " + entry.moduleName); throw new Error("Failed to load Page from entry.moduleName: " + entry.moduleName);
} }
} }
@ -142,7 +145,7 @@ function pageFromBuilder(moduleNamePath: string, moduleExports: any): Page {
} }
// Or check if the file exists in the app modules and load the page from XML. // Or check if the file exists in the app modules and load the page from XML.
page = builder.loadPage(moduleNamePath, fileName, moduleExports); page = loadPage(moduleNamePath, fileName, moduleExports);
} }
// Attempts to implement https://github.com/NativeScript/NativeScript/issues/1311 // Attempts to implement https://github.com/NativeScript/NativeScript/issues/1311
@ -324,7 +327,7 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
} }
let backstackVisibleValue = entry.entry.backstackVisible; let backstackVisibleValue = entry.entry.backstackVisible;
let backstackHidden = isDefined(backstackVisibleValue) && !backstackVisibleValue; let backstackHidden = backstackVisibleValue !== undefined && !backstackVisibleValue;
return !backstackHidden; return !backstackHidden;
} }
@ -458,11 +461,11 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
} }
public _getIsAnimatedNavigation(entry: NavigationEntry): boolean { public _getIsAnimatedNavigation(entry: NavigationEntry): boolean {
if (entry && isDefined(entry.animated)) { if (entry && entry.animated !== undefined) {
return entry.animated; return entry.animated;
} }
if (isDefined(this.animated)) { if (this.animated !== undefined) {
return this.animated; return this.animated;
} }
@ -471,20 +474,20 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
public _getNavigationTransition(entry: NavigationEntry): NavigationTransition { public _getNavigationTransition(entry: NavigationEntry): NavigationTransition {
if (entry) { if (entry) {
if (isIOS && isDefined(entry.transitioniOS)) { if (isIOS && entry.transitioniOS !== undefined) {
return entry.transitioniOS; return entry.transitioniOS;
} }
if (isAndroid && isDefined(entry.transitionAndroid)) { if (isAndroid && entry.transitionAndroid !== undefined) {
return entry.transitionAndroid; return entry.transitionAndroid;
} }
if (isDefined(entry.transition)) { if (entry.transition !== undefined) {
return entry.transition; return entry.transition;
} }
} }
if (isDefined(this.transition)) { if (this.transition !== undefined) {
return this.transition; return this.transition;
} }

View File

@ -1,12 +1,14 @@
import { // Definitions.
import {
AndroidFrame as AndroidFrameDefinition, BackstackEntry, AndroidFrame as AndroidFrameDefinition, BackstackEntry,
NavigationTransition, AndroidFragmentCallbacks, AndroidActivityCallbacks NavigationTransition, AndroidFragmentCallbacks, AndroidActivityCallbacks
} from "ui/frame"; } from "ui/frame";
import { FrameBase, NavigationContext, stack, goBack } from "./frame-common"; import { Page } from "ui/page";
import { Page, View, Observable, traceEnabled, traceWrite, traceCategories } from "ui/page";
// Types.
import { FrameBase, application, NavigationContext, stack, goBack, View, Observable, traceEnabled, traceWrite, traceCategories } from "./frame-common";
import { DIALOG_FRAGMENT_TAG } from "../page/constants"; import { DIALOG_FRAGMENT_TAG } from "../page/constants";
import * as transitionModule from "ui/transition"; import * as transitionModule from "ui/transition";
import * as application from "application";
export * from "./frame-common"; export * from "./frame-common";
@ -182,7 +184,7 @@ export class Frame extends FrameBase {
transitionModule._clearForwardTransitions(currentFragment); transitionModule._clearForwardTransitions(currentFragment);
if (animated && navigationTransition) { if (animated && navigationTransition) {
transitionModule._setAndroidFragmentTransitions(navigationTransition, currentFragment, newFragment, fragmentTransaction); transitionModule._setAndroidFragmentTransitions(this.android.cachePagesOnNavigate, navigationTransition, currentFragment, newFragment, fragmentTransaction);
} }
} }

View File

@ -1,10 +1,10 @@
import { iOSFrame as iOSFrameDefinition, BackstackEntry, NavigationTransition } from "ui/frame"; // Definitions.
import { FrameBase } from "./frame-common"; import { iOSFrame as iOSFrameDefinition, BackstackEntry, NavigationTransition } from "ui/frame";
import { Page, View, traceEnabled, traceWrite, traceCategories, isCategorySet } from "ui/page"; import { Page } from "ui/page";
import * as transitionModule from "ui/transition"; //Types.
import * as application from "application"; import { FrameBase, View, application, layout, traceEnabled, traceWrite, traceCategories, isCategorySet } from "./frame-common";
import * as utils from "utils/utils"; import { _createIOSAnimatedTransitioning } from "ui/transition";
import * as uiUtils from "ui/utils"; import * as uiUtils from "ui/utils";
export * from "./frame-common"; export * from "./frame-common";
@ -272,11 +272,11 @@ export class Frame extends FrameBase {
} }
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void { public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
let width = utils.layout.getMeasureSpecSize(widthMeasureSpec); let width = layout.getMeasureSpecSize(widthMeasureSpec);
let widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec); let widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
let height = utils.layout.getMeasureSpecSize(heightMeasureSpec); let height = layout.getMeasureSpecSize(heightMeasureSpec);
let heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec); let heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
this._widthMeasureSpec = widthMeasureSpec; this._widthMeasureSpec = widthMeasureSpec;
this._heightMeasureSpec = heightMeasureSpec; this._heightMeasureSpec = heightMeasureSpec;
@ -298,10 +298,10 @@ export class Frame extends FrameBase {
// If background does not span under statusbar - reduce available height. // If background does not span under statusbar - reduce available height.
let heightSpec: number = this._heightMeasureSpec; let heightSpec: number = this._heightMeasureSpec;
if (page && !page.backgroundSpanUnderStatusBar && !this.parent) { if (page && !page.backgroundSpanUnderStatusBar && !this.parent) {
let height = utils.layout.getMeasureSpecSize(this._heightMeasureSpec); let height = layout.getMeasureSpecSize(this._heightMeasureSpec);
let heightMode = utils.layout.getMeasureSpecMode(this._heightMeasureSpec); let heightMode = layout.getMeasureSpecMode(this._heightMeasureSpec);
let statusBarHeight = uiUtils.ios.getStatusBarHeight(); let statusBarHeight = uiUtils.ios.getStatusBarHeight();
heightSpec = utils.layout.makeMeasureSpec(height - statusBarHeight, heightMode); heightSpec = layout.makeMeasureSpec(height - statusBarHeight, heightMode);
} }
return View.measureChild(this, page, this._widthMeasureSpec, heightSpec); return View.measureChild(this, page, this._widthMeasureSpec, heightSpec);
@ -465,7 +465,7 @@ class UINavigationControllerAnimatedDelegate extends NSObject implements UINavig
} }
let curve = _getNativeCurve(navigationTransition); let curve = _getNativeCurve(navigationTransition);
let animationController = transitionModule._createIOSAnimatedTransitioning(navigationTransition, curve, operation, fromVC, toVC); let animationController = _createIOSAnimatedTransitioning(navigationTransition, curve, operation, fromVC, toVC);
return animationController; return animationController;
} }
} }

View File

@ -1,9 +1,6 @@
import { GestureEventData as GestureEventData, GesturesObserver as GesturesObserverDefinition } from "ui/gestures"; import { GestureEventData as GestureEventData, GesturesObserver as GesturesObserverDefinition } from "ui/gestures";
import { View } from "ui/core/view"; import { View } from "ui/core/view";
// Only types:
export { View, EventData } from "ui/core/view";
export enum GestureTypes { export enum GestureTypes {
tap = 1 << 0, tap = 1 << 0,
doubleTap = 1 << 1, doubleTap = 1 << 1,

View File

@ -1,7 +1,10 @@
import { GestureEventData, SwipeGestureEventData, PanGestureEventData, RotationGestureEventData } from "ui/gestures"; // Definitions.
import { GestureEventData, SwipeGestureEventData, PanGestureEventData, RotationGestureEventData } from "ui/gestures";
import { View, EventData } from "ui/core/view";
// Types.
import { import {
GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection, GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection
View, EventData
} from "./gestures-common"; } from "./gestures-common";
// Import layout from utils directly to avoid circular references // Import layout from utils directly to avoid circular references

View File

@ -1,5 +1,9 @@
import { GestureEventData, SwipeGestureEventData, PanGestureEventData, RotationGestureEventData, PinchGestureEventData } from "ui/gestures"; // Definitions.
import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection, View, EventData } from "./gestures-common"; import { GestureEventData, SwipeGestureEventData, PanGestureEventData, RotationGestureEventData, PinchGestureEventData } from "ui/gestures";
import { View, EventData } from "ui/core/view";
// Types.
import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection } from "./gestures-common";
import { ios } from "utils/utils"; import { ios } from "utils/utils";
import getter = ios.getter; import getter = ios.getter;
@ -20,6 +24,9 @@ class UIGestureRecognizerDelegateImpl extends NSObject implements UIGestureRecog
let recognizerDelegateInstance: UIGestureRecognizerDelegateImpl = <UIGestureRecognizerDelegateImpl>UIGestureRecognizerDelegateImpl.new(); let recognizerDelegateInstance: UIGestureRecognizerDelegateImpl = <UIGestureRecognizerDelegateImpl>UIGestureRecognizerDelegateImpl.new();
class UIGestureRecognizerImpl extends NSObject { class UIGestureRecognizerImpl extends NSObject {
public static ObjCExposedMethods = {
"recognize": { returns: interop.types.void, params: [UIGestureRecognizer] }
};
private _owner: WeakRef<GesturesObserver>; private _owner: WeakRef<GesturesObserver>;
private _type: any; private _type: any;
@ -42,10 +49,6 @@ class UIGestureRecognizerImpl extends NSObject {
return handler; return handler;
} }
public static ObjCExposedMethods = {
"recognize": { returns: interop.types.void, params: [UIGestureRecognizer] }
};
public recognize(recognizer: UIGestureRecognizer): void { public recognize(recognizer: UIGestureRecognizer): void {
let owner = this._owner.get(); let owner = this._owner.get();
let callback = this._callback ? this._callback : (owner ? owner.callback : null); let callback = this._callback ? this._callback : (owner ? owner.callback : null);

View File

@ -1,6 +1,7 @@
import { Label as LabelDefinition } from "ui/label"; import { Label as LabelDefinition } from "ui/label";
import { Background } from "ui/styling/background";
import { import {
Background, TextBase, View, layout, backgroundInternalProperty, TextBase, View, layout, backgroundInternalProperty,
borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty, borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty,
paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty, whiteSpaceProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty, whiteSpaceProperty,
Length, WhiteSpace Length, WhiteSpace

View File

@ -146,7 +146,6 @@ export class ListPicker extends ListPickerBase {
textColor: this._editText ? this._editText.getTextColors().getDefaultColor() : -1 textColor: this._editText ? this._editText.getTextColors().getDefaultColor() : -1
} }
} }
set [colorProperty.native](value: { wheelColor: number, textColor: number } | Color) { set [colorProperty.native](value: { wheelColor: number, textColor: number } | Color) {
let color: number; let color: number;
let wheelColor: number; let wheelColor: number;

View File

@ -1,5 +1,5 @@
import { ListView as ListViewDefinition, ItemsSource } from "ui/list-view"; import { ListView as ListViewDefinition, ItemsSource } from "ui/list-view";
import { CoercibleProperty, CssProperty, Style, View, Template, KeyedTemplate, Length, Property, Color, lengthComparer, Observable } from "ui/core/view"; import { CoercibleProperty, CssProperty, Style, View, Template, KeyedTemplate, Length, Property, Color, Observable } from "ui/core/view";
import { parse, parseMultipleTemplates } from "ui/builder"; import { parse, parseMultipleTemplates } from "ui/builder";
import { Label } from "ui/label"; import { Label } from "ui/label";
import { ObservableArray, ChangedData } from "data/observable-array"; import { ObservableArray, ChangedData } from "data/observable-array";
@ -171,7 +171,7 @@ const defaultRowHeight: Length = "auto";
* Represents the observable property backing the rowHeight property of each ListView instance. * Represents the observable property backing the rowHeight property of each ListView instance.
*/ */
export const rowHeightProperty = new CoercibleProperty<ListViewBase, Length>({ export const rowHeightProperty = new CoercibleProperty<ListViewBase, Length>({
name: "rowHeight", defaultValue: defaultRowHeight, equalityComparer: lengthComparer, name: "rowHeight", defaultValue: defaultRowHeight, equalityComparer: Length.equals,
coerceValue: (target, value) => { coerceValue: (target, value) => {
// We coerce to default value if we don't have display density. // We coerce to default value if we don't have display density.
return target._nativeView ? value : defaultRowHeight; return target._nativeView ? value : defaultRowHeight;

View File

@ -1,11 +1,10 @@
import { import {
PageBase, View, layout, PageBase, View, layout,
actionBarHiddenProperty, statusBarStyleProperty, actionBarHiddenProperty, statusBarStyleProperty,
traceEnabled, traceWrite, traceCategories, PercentLength traceEnabled, traceWrite, traceCategories, PercentLength, Color
} from "./page-common"; } from "./page-common";
import { ios as iosApp } from "application"; import { ios as iosApp } from "application";
import { device } from "platform"; import { device } from "platform";
import { Color } from "color";
import * as uiUtils from "ui/utils"; import * as uiUtils from "ui/utils";
export * from "./page-common"; export * from "./page-common";

View File

@ -1,5 +1,6 @@
import { import { Font } from "ui/styling/font";
SearchBarBase, Font, Color, colorProperty, backgroundColorProperty, backgroundInternalProperty, fontInternalProperty, import {
SearchBarBase, Color, colorProperty, backgroundColorProperty, backgroundInternalProperty, fontInternalProperty,
textProperty, hintProperty, textFieldHintColorProperty, textFieldBackgroundColorProperty, fontSizeProperty textProperty, hintProperty, textFieldHintColorProperty, textFieldBackgroundColorProperty, fontSizeProperty
} from "./search-bar-common"; } from "./search-bar-common";
import { ad } from "utils/utils"; import { ad } from "utils/utils";

View File

@ -1,5 +1,6 @@
import { import { Font } from "ui/styling/font";
SearchBarBase, Font, Color, colorProperty, backgroundColorProperty, backgroundInternalProperty, fontInternalProperty, import {
SearchBarBase, Color, colorProperty, backgroundColorProperty, backgroundInternalProperty, fontInternalProperty,
textProperty, hintProperty, textFieldHintColorProperty, textFieldBackgroundColorProperty textProperty, hintProperty, textFieldHintColorProperty, textFieldBackgroundColorProperty
} from "./search-bar-common"; } from "./search-bar-common";

View File

@ -1,6 +1,7 @@
import { import { Font } from "ui/styling/font";
import {
SegmentedBarItemBase, SegmentedBarBase, selectedIndexProperty, itemsProperty, selectedBackgroundColorProperty, SegmentedBarItemBase, SegmentedBarBase, selectedIndexProperty, itemsProperty, selectedBackgroundColorProperty,
colorProperty, fontInternalProperty, fontSizeProperty, Color, Font, initNativeView colorProperty, fontInternalProperty, fontSizeProperty, Color, initNativeView
} from "./segmented-bar-common"; } from "./segmented-bar-common";
export * from "./segmented-bar-common"; export * from "./segmented-bar-common";

View File

@ -1,6 +1,7 @@
import { import { Font } from "ui/styling/font";
import {
SegmentedBarItemBase, SegmentedBarBase, selectedIndexProperty, itemsProperty, selectedBackgroundColorProperty, SegmentedBarItemBase, SegmentedBarBase, selectedIndexProperty, itemsProperty, selectedBackgroundColorProperty,
colorProperty, fontInternalProperty, Color, Font colorProperty, fontInternalProperty, Color
} from "./segmented-bar-common"; } from "./segmented-bar-common";
import { ios } from "utils/utils"; import { ios } from "utils/utils";

View File

@ -1,7 +1,7 @@
import { import { Background } from "ui/styling/background";
import {
SliderBase, valueProperty, minValueProperty, maxValueProperty, SliderBase, valueProperty, minValueProperty, maxValueProperty,
colorProperty, backgroundColorProperty, backgroundInternalProperty, colorProperty, backgroundColorProperty, backgroundInternalProperty, Color
Color, Background
} from "./slider-common"; } from "./slider-common";
export * from "./slider-common"; export * from "./slider-common";
@ -26,10 +26,10 @@ function initializeSeekBarChangeListener(): void {
onProgressChanged(seekBar: android.widget.SeekBar, progress: number, fromUser: boolean): void { onProgressChanged(seekBar: android.widget.SeekBar, progress: number, fromUser: boolean): void {
const owner = this.owner; const owner = this.owner;
if (!owner._supressNativeValue) { if (!owner._supressNativeValue) {
let newValue: number = seekBar.getProgress() + owner.minValue; let newValue: number = seekBar.getProgress() + owner.minValue;
valueProperty.nativeValueChange(owner, newValue); valueProperty.nativeValueChange(owner, newValue);
} }
} }
onStartTrackingTouch(seekBar: android.widget.SeekBar): void { onStartTrackingTouch(seekBar: android.widget.SeekBar): void {

View File

@ -1,7 +1,9 @@
import { import { Background } from "ui/styling/background";
import {
SliderBase, valueProperty, minValueProperty, maxValueProperty, SliderBase, valueProperty, minValueProperty, maxValueProperty,
colorProperty, backgroundColorProperty, backgroundInternalProperty, colorProperty, backgroundColorProperty, backgroundInternalProperty,
Color, Background Color
} from "./slider-common"; } from "./slider-common";
export * from "./slider-common"; export * from "./slider-common";

View File

@ -1,6 +1,10 @@
// Deifinitions.
import { Background as BackgroundDefinition, BackgroundDrawParams } from "ui/styling/background"; import { Background as BackgroundDefinition, BackgroundDrawParams } from "ui/styling/background";
import { Color, BackgroundRepeat } from "ui/core/view"; import { BackgroundRepeat } from "ui/core/view";
import { ImageSource } from "image-source"; import { ImageSource } from "image-source";
// Types.
import { Color } from "color";
import { CSSValue, parse as cssParse } from "css-value"; import { CSSValue, parse as cssParse } from "css-value";
export class Background implements BackgroundDefinition { export class Background implements BackgroundDefinition {

View File

@ -1,6 +1,7 @@
declare module "ui/styling/background" { declare module "ui/styling/background" {
import { ImageSource } from "image-source"; import { ImageSource } from "image-source";
import { View, Color, BackgroundRepeat } from "ui/core/view"; import { Color } from "color";
import { View, BackgroundRepeat } from "ui/core/view";
export interface BackgroundDrawParams { export interface BackgroundDrawParams {
repeatX: boolean; repeatX: boolean;

View File

@ -1,4 +1,5 @@
import { View, Color, Point } from "ui/core/view"; import { Color } from "color";
import { View, Point } from "ui/core/view";
import { Background } from "./background-common"; import { Background } from "./background-common";
import { ios as utilsIos } from "utils/utils"; import { ios as utilsIos } from "utils/utils";
import { layout } from "utils/utils"; import { layout } from "utils/utils";

View File

@ -0,0 +1,151 @@
declare module "ui/styling/style-properties" {
import { Color } from "color";
import { Style, CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty } from "ui/core/properties";
import { Font, FontStyle, FontWeight } from "ui/styling/font";
import { Background } from "ui/styling/background";
export type Length = "auto" | number | {
readonly unit: "dip" | "px";
readonly value: number;
}
export namespace Length {
export function parse(text: string): Length;
export function equals(a: Length, b: Length): boolean;
/**
* Converts Length unit to device pixels.
* @param length The Length to convert.
* @param auto Value to use for conversion of "auto".
*/
export function toDevicePixels(length: Length, auto: number): number;
export function convertToString(length: Length): string;
}
export type PercentLength = "auto" | number | {
readonly unit: "%" | "dip" | "px";
/**
* Length value. When unit is "%" the value is normalized (ex. for 5% the value is 0.05)
*/
readonly value: number;
}
export namespace PercentLength {
export function parse(text: string): PercentLength;
export function equals(a: PercentLength, b: PercentLength): boolean;
/**
* Converts PercentLength unit to device pixels.
* @param length The PercentLength to convert.
* @param auto Value to use for conversion of "auto".
* @param parentAvailableWidth Value to use as base when converting percent unit.
*/
export function toDevicePixels(length: PercentLength, auto: number, parentAvailableWidth: number): number;
export function convertToString(length: PercentLength): string;
}
export const zeroLength: Length;
export const rotateProperty: CssAnimationProperty<Style, number>;
export const scaleXProperty: CssAnimationProperty<Style, number>;
export const scaleYProperty: CssAnimationProperty<Style, number>;
export const translateXProperty: CssAnimationProperty<Style, Length>;
export const translateYProperty: CssAnimationProperty<Style, Length>;
export const clipPathProperty: CssProperty<Style, string>;
export const colorProperty: InheritedCssProperty<Style, Color>;
export const backgroundColorProperty: CssAnimationProperty<Style, Color>;
export const backgroundImageProperty: CssProperty<Style, string>;
export const backgroundRepeatProperty: CssProperty<Style, BackgroundRepeat>;
export const backgroundSizeProperty: CssProperty<Style, string>;
export const backgroundPositionProperty: CssProperty<Style, string>;
export const borderColorProperty: ShorthandProperty<Style, string | Color>;
export const borderTopColorProperty: CssProperty<Style, Color>;
export const borderRightColorProperty: CssProperty<Style, Color>;
export const borderBottomColorProperty: CssProperty<Style, Color>;
export const borderLeftColorProperty: CssProperty<Style, Color>;
export const borderWidthProperty: ShorthandProperty<Style, string | Length>;
export const borderTopWidthProperty: CssProperty<Style, Length>;
export const borderRightWidthProperty: CssProperty<Style, Length>;
export const borderBottomWidthProperty: CssProperty<Style, Length>;
export const borderLeftWidthProperty: CssProperty<Style, Length>;
export const borderRadiusProperty: ShorthandProperty<Style, string | Length>;
export const borderTopLeftRadiusProperty: CssProperty<Style, Length>;
export const borderTopRightRadiusProperty: CssProperty<Style, Length>;
export const borderBottomRightRadiusProperty: CssProperty<Style, Length>;
export const borderBottomLeftRadiusProperty: CssProperty<Style, Length>;
export const zIndexProperty: CssProperty<Style, number>;
export const visibilityProperty: CssProperty<Style, Visibility>;
export const opacityProperty: CssAnimationProperty<Style, number>;
export const minWidthProperty: CssProperty<Style, Length>;
export const minHeightProperty: CssProperty<Style, Length>;
export const widthProperty: CssProperty<Style, Length>;
export const heightProperty: CssProperty<Style, Length>;
export const marginProperty: ShorthandProperty<Style, string | PercentLength>;
export const marginLeftProperty: CssProperty<Style, PercentLength>;
export const marginRightProperty: CssProperty<Style, PercentLength>;
export const marginTopProperty: CssProperty<Style, PercentLength>;
export const marginBottomProperty: CssProperty<Style, PercentLength>;
export const paddingProperty: ShorthandProperty<Style, string | Length>;
export const paddingLeftProperty: CssProperty<Style, Length>;
export const paddingRightProperty: CssProperty<Style, Length>;
export const paddingTopProperty: CssProperty<Style, Length>;
export const paddingBottomProperty: CssProperty<Style, Length>;
export const horizontalAlignmentProperty: CssProperty<Style, HorizontalAlignment>;
export const verticalAlignmentProperty: CssProperty<Style, VerticalAlignment>;
export const fontSizeProperty: InheritedCssProperty<Style, number>;
export const fontFamilyProperty: InheritedCssProperty<Style, string>;
export const fontStyleProperty: InheritedCssProperty<Style, FontStyle>;
export const fontWeightProperty: InheritedCssProperty<Style, FontWeight>;
export const backgroundInternalProperty: CssProperty<Style, Background>;
export const fontInternalProperty: InheritedCssProperty<Style, Font>;
export type BackgroundRepeat = "repeat" | "repeat-x" | "repeat-y" | "no-repeat";
export namespace BackgroundRepeat {
export const REPEAT: "repeat";
export const REPEAT_X: "repeat-x";
export const REPEAT_Y: "repeat-y";
export const NO_REPEAT: "no-repeat";
export function isValid(value: any): boolean;
export function parse(value: string): BackgroundRepeat;
}
export type Visibility = "visible" | "hidden" | "collapse";
export namespace Visibility {
export const VISIBLE: "visible";
export const HIDDEN: "hidden";
export const COLLAPSE: "collapse";
export function isValid(value: any): boolean;
export function parse(value: string): Visibility;
}
export type HorizontalAlignment = "left" | "center" | "right" | "stretch";
export namespace HorizontalAlignment {
export const LEFT: "left";
export const CENTER: "center";
export const RIGHT: "right";
export const STRETCH: "stretch";
export function isValid(value: any): boolean;
export function parse(value: string): HorizontalAlignment;
}
export type VerticalAlignment = "top" | "middle" | "bottom" | "stretch";
export namespace VerticalAlignment {
export const TOP: "top";
export const MIDDLE: "middle";
export const BOTTOM: "bottom";
export const STRETCH: "stretch";
export function isValid(value: any): boolean;
export function parse(value: string): VerticalAlignment;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
import { ViewBase, resetCSSProperties } from "ui/core/view-base"; import { ViewBase } from "ui/core/view-base";
import { resetCSSProperties } from "ui/core/properties";
import { SyntaxTree, Keyframes, parse as parseCss, Node } from "css"; import { SyntaxTree, Keyframes, parse as parseCss, Node } from "css";
import { RuleSet, SelectorsMap, SelectorCore, SelectorsMatch, ChangeMap, fromAstNodes } from "ui/styling/css-selector"; import { RuleSet, SelectorsMap, SelectorCore, SelectorsMatch, ChangeMap, fromAstNodes } from "ui/styling/css-selector";
import { write as traceWrite, categories as traceCategories, messageType as traceMessageType } from "trace"; import { write as traceWrite, categories as traceCategories, messageType as traceMessageType } from "trace";

View File

@ -1,7 +1,9 @@
declare module "ui/styling/style" { declare module "ui/styling/style" {
import { Length, PercentLength, Color, Background, Font, ViewBase, Observable, BackgroundRepeat, Visibility, HorizontalAlignment, VerticalAlignment} from "ui/core/view"; import { Color } from "color";
import { Background } from "ui/styling/background";
import { Length, PercentLength, ViewBase, Observable, BackgroundRepeat, Visibility, HorizontalAlignment, VerticalAlignment } from "ui/core/view";
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from "ui/text-base"; import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from "ui/text-base";
import { FontStyle, FontWeight } from "ui/styling/font"; import { Font, FontStyle, FontWeight } from "ui/styling/font";
export interface Thickness { export interface Thickness {
left: number; left: number;

View File

@ -1,5 +1,8 @@
import { Style as StyleDefinition } from "ui/styling/style"; import { Style as StyleDefinition } from "ui/styling/style";
import { Length, PercentLength, Color, Background, Font, ViewBase, BackgroundRepeat, Visibility, HorizontalAlignment, VerticalAlignment } from "ui/core/view"; import { Color } from "color";
import { Font } from "ui/styling/font";
import { Background } from "ui/styling/background";
import { Length, PercentLength, ViewBase, BackgroundRepeat, Visibility, HorizontalAlignment, VerticalAlignment } from "ui/core/view";
import { Observable } from "data/observable"; import { Observable } from "data/observable";
import { import {
@ -298,11 +301,4 @@ Style.prototype.effectivePaddingLeft = 0;
Style.prototype.effectiveBorderTopWidth = 0; Style.prototype.effectiveBorderTopWidth = 0;
Style.prototype.effectiveBorderRightWidth = 0; Style.prototype.effectiveBorderRightWidth = 0;
Style.prototype.effectiveBorderBottomWidth = 0; Style.prototype.effectiveBorderBottomWidth = 0;
Style.prototype.effectiveBorderLeftWidth = 0; Style.prototype.effectiveBorderLeftWidth = 0;
// Property registration
// register default shorthand callbacks.
// styleProperty.registerShorthandCallback("font", onFontChanged);
// styleProperty.registerShorthandCallback("margin", onMarginChanged);
// styleProperty.registerShorthandCallback("padding", onPaddingChanged);
// styleProperty.registerShorthandCallback("transform", onTransformChanged);

View File

@ -1,9 +1,11 @@
import { Font } from "ui/styling/font";
import { import {
TabViewBase, TabViewItemBase, itemsProperty, selectedIndexProperty, TabViewBase, TabViewItemBase, itemsProperty, selectedIndexProperty,
tabTextColorProperty, tabBackgroundColorProperty, selectedTabTextColorProperty, tabTextColorProperty, tabBackgroundColorProperty, selectedTabTextColorProperty,
androidSelectedTabHighlightColorProperty, androidOffscreenTabLimitProperty, androidSelectedTabHighlightColorProperty, androidOffscreenTabLimitProperty,
fontSizeProperty, fontInternalProperty, View, layout, Color, Font, fontSizeProperty, fontInternalProperty, View, layout,
traceCategory, traceEnabled, traceWrite, initNativeView traceCategory, traceEnabled, traceWrite, initNativeView, Color
} from "./tab-view-common" } from "./tab-view-common"
import { textTransformProperty, TextTransform, getTransformedText } from "ui/text-base"; import { textTransformProperty, TextTransform, getTransformedText } from "ui/text-base";
import { fromFileOrResource } from "image-source"; import { fromFileOrResource } from "image-source";
@ -376,7 +378,7 @@ export class TabView extends TabViewBase {
if (value instanceof Color) { if (value instanceof Color) {
this._tabLayout.setBackgroundColor(value.android); this._tabLayout.setBackgroundColor(value.android);
} else { } else {
this._tabLayout.setBackground(value.newDrawable()); this._tabLayout.setBackground(value ? value.newDrawable() : null);
} }
} }
@ -384,7 +386,7 @@ export class TabView extends TabViewBase {
return this._tabLayout.getTabTextColor(); return this._tabLayout.getTabTextColor();
} }
set [tabTextColorProperty.native](value: number | Color) { set [tabTextColorProperty.native](value: number | Color) {
let color = value instanceof Color ? value.android : value; const color = value instanceof Color ? value.android : value;
this._tabLayout.setTabTextColor(color); this._tabLayout.setTabTextColor(color);
} }
@ -392,7 +394,7 @@ export class TabView extends TabViewBase {
return this._tabLayout.getSelectedTabTextColor(); return this._tabLayout.getSelectedTabTextColor();
} }
set [selectedTabTextColorProperty.native](value: number | Color) { set [selectedTabTextColorProperty.native](value: number | Color) {
let color = value instanceof Color ? value.android : value; const color = value instanceof Color ? value.android : value;
this._tabLayout.setSelectedTabTextColor(color); this._tabLayout.setSelectedTabTextColor(color);
} }
@ -401,7 +403,7 @@ export class TabView extends TabViewBase {
} }
set [androidSelectedTabHighlightColorProperty.native](value: number | Color) { set [androidSelectedTabHighlightColorProperty.native](value: number | Color) {
let tabLayout = this._tabLayout; let tabLayout = this._tabLayout;
let color = value instanceof Color ? value.android : value; const color = value instanceof Color ? value.android : value;
tabLayout.setSelectedIndicatorColors([color]); tabLayout.setSelectedIndicatorColors([color]);
} }
} }

View File

@ -1,7 +1,9 @@
import { import { Font } from "ui/styling/font";
import {
TabViewBase, TabViewItemBase, itemsProperty, selectedIndexProperty, TabViewBase, TabViewItemBase, itemsProperty, selectedIndexProperty,
tabTextColorProperty, tabBackgroundColorProperty, selectedTabTextColorProperty, iosIconRenderingModeProperty, tabTextColorProperty, tabBackgroundColorProperty, selectedTabTextColorProperty, iosIconRenderingModeProperty,
Font, View, fontInternalProperty, layout, Color, traceEnabled, traceWrite, traceCategories View, fontInternalProperty, layout, traceEnabled, traceWrite, traceCategories, Color
} from "./tab-view-common" } from "./tab-view-common"
import { textTransformProperty, TextTransform, getTransformedText } from "ui/text-base"; import { textTransformProperty, TextTransform, getTransformedText } from "ui/text-base";
@ -397,7 +399,7 @@ export class TabView extends TabViewBase {
get [tabTextColorProperty.native](): UIColor { get [tabTextColorProperty.native](): UIColor {
return null; return null;
} }
set [tabTextColorProperty.native](value: UIColor) { set [tabTextColorProperty.native](value: UIColor | Color) {
this._ios.tabBar.tintColor = value instanceof Color ? value.ios : value; this._ios.tabBar.tintColor = value instanceof Color ? value.ios : value;
this._updateIOSTabBarColorsAndFonts(); this._updateIOSTabBarColorsAndFonts();
} }

View File

@ -1,9 +1,11 @@
import { import { Font } from "ui/styling/font";
import {
TextBaseCommon, formattedTextProperty, textAlignmentProperty, textDecorationProperty, fontSizeProperty, TextBaseCommon, formattedTextProperty, textAlignmentProperty, textDecorationProperty, fontSizeProperty,
textProperty, textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty, textProperty, textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty,
whiteSpaceProperty, Font, Color, FormattedString, TextDecoration, TextAlignment, TextTransform, WhiteSpace, whiteSpaceProperty, FormattedString, TextDecoration, TextAlignment, TextTransform, WhiteSpace,
paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length, paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length,
layout, Span layout, Span, Color
} from "./text-base-common"; } from "./text-base-common";
import { _isSet as isSet } from "ui/core/properties"; import { _isSet as isSet } from "ui/core/properties";

View File

@ -1,7 +1,8 @@
import { import { Font } from "ui/styling/font";
import {
TextBaseCommon, textProperty, formattedTextProperty, textAlignmentProperty, textDecorationProperty, TextBaseCommon, textProperty, formattedTextProperty, textAlignmentProperty, textDecorationProperty,
textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty, Font, Color, FormattedString, textTransformProperty, letterSpacingProperty, colorProperty, fontInternalProperty, FormattedString,
TextDecoration, TextAlignment, TextTransform, Span TextDecoration, TextAlignment, TextTransform, Span, Color
} from "./text-base-common"; } from "./text-base-common";
import { _isSet as isSet } from "ui/core/properties"; import { _isSet as isSet } from "ui/core/properties";

View File

@ -1,6 +1,6 @@
import { import {
TextFieldBase, Color, secureProperty, textProperty, hintProperty, colorProperty, placeholderColorProperty, TextFieldBase, secureProperty, textProperty, hintProperty, colorProperty, placeholderColorProperty,
Length, paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty, _updateCharactersInRangeReplacementString Length, paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty, _updateCharactersInRangeReplacementString, Color
} from "./text-field-common"; } from "./text-field-common";
export * from "./text-field-common"; export * from "./text-field-common";

View File

@ -2,10 +2,10 @@
import { import {
EditableTextBase, editableProperty, hintProperty, textProperty, colorProperty, EditableTextBase, editableProperty, hintProperty, textProperty, colorProperty,
borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty, borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty,
paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty, Length, _updateCharactersInRangeReplacementString paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty,
Length, _updateCharactersInRangeReplacementString, Color
} from "ui/editable-text-base"; } from "ui/editable-text-base";
import { Color } from "color";
import { ios } from "utils/utils"; import { ios } from "utils/utils";
export * from "ui/editable-text-base"; export * from "ui/editable-text-base";

View File

@ -1,7 +1,8 @@
import { TimePickerBase, timeProperty, import {
TimePickerBase, timeProperty,
minuteProperty, minMinuteProperty, maxMinuteProperty, minuteProperty, minMinuteProperty, maxMinuteProperty,
hourProperty, minHourProperty, maxHourProperty, colorProperty } from "./time-picker-common"; hourProperty, minHourProperty, maxHourProperty, colorProperty, Color
import { Color } from "color"; } from "./time-picker-common";
import { ios } from "utils/utils"; import { ios } from "utils/utils";
import getter = ios.getter; import getter = ios.getter;
@ -99,11 +100,12 @@ export class TimePicker extends TimePickerBase {
this.nativeView.minuteInterval = value; this.nativeView.minuteInterval = value;
} }
get [colorProperty.native](): Color { get [colorProperty.native](): UIColor {
return ios.getColor(this.nativeView.valueForKey("textColor")); return this.nativeView.valueForKey("textColor");
} }
set [colorProperty.native](value: Color) { set [colorProperty.native](value: Color | UIColor) {
this.nativeView.setValueForKey(value.ios, "textColor"); const color = value instanceof Color ? value.ios : value;
this.nativeView.setValueForKey(color, "textColor");
} }
} }

View File

@ -1,6 +1,9 @@
import { Transition as TransitionDefinition } from "ui/transition"; // Definitions.
import { NavigationTransition, BackstackEntry, topmost } from "ui/frame"; import { Transition as TransitionDefinition } from "ui/transition";
import { Page } from "ui/page"; import { Page } from "ui/page";
import { NavigationTransition, BackstackEntry } from "ui/frame";
// Types.
import { getClass } from "utils/types"; import { getClass } from "utils/types";
import { device } from "platform"; import { device } from "platform";
import { _resolveAnimationCurve } from "ui/animation"; import { _resolveAnimationCurve } from "ui/animation";
@ -129,7 +132,7 @@ export function _clearForwardTransitions(fragment: any): void {
} }
} }
export function _setAndroidFragmentTransitions(navigationTransition: NavigationTransition, currentFragment: any, newFragment: any, fragmentTransaction: any): void { export function _setAndroidFragmentTransitions(cachePagesOnNavigate: boolean, navigationTransition: NavigationTransition, currentFragment: any, newFragment: any, fragmentTransaction: android.app.FragmentTransaction): void {
traceWrite(`Setting Android Fragment Transitions...`, traceCategories.Transition); traceWrite(`Setting Android Fragment Transitions...`, traceCategories.Transition);
let name; let name;
if (navigationTransition.name) { if (navigationTransition.name) {
@ -142,7 +145,7 @@ export function _setAndroidFragmentTransitions(navigationTransition: NavigationT
// The exit transition of the current fragment ends immediately, the page UI is removed from the visual tree // The exit transition of the current fragment ends immediately, the page UI is removed from the visual tree
// and a white spot is left in its place making the transition ugly. // and a white spot is left in its place making the transition ugly.
// So we will use the "old" pre-Lollipop transitions in this particular case. // So we will use the "old" pre-Lollipop transitions in this particular case.
if (topmost().android.cachePagesOnNavigate && _sdkVersion() === 23) { if (cachePagesOnNavigate && _sdkVersion() === 23) {
useLollipopTransition = false; useLollipopTransition = false;
} }

View File

@ -21,7 +21,7 @@
//@private //@private
export function _clearBackwardTransitions(fragment: any): void; export function _clearBackwardTransitions(fragment: any): void;
export function _clearForwardTransitions(fragment: any): void; export function _clearForwardTransitions(fragment: any): void;
export function _setAndroidFragmentTransitions(navigationTransition: NavigationTransition, currentFragment: any, newFragment: any, fragmentTransaction: any): void; export function _setAndroidFragmentTransitions(cachePagesOnNavigate: boolean, navigationTransition: NavigationTransition, currentFragment: android.app.Fragment, newFragment: android.app.Fragment, fragmentTransaction: android.app.FragmentTransaction): void;
export function _onFragmentCreateAnimator(fragment: any, nextAnim: number): any; export function _onFragmentCreateAnimator(fragment: any, nextAnim: number): any;
export function _onFragmentShown(fragment: any, isBack: boolean): void; export function _onFragmentShown(fragment: any, isBack: boolean): void;
export function _onFragmentHidden(fragment: any, isBack: boolean, destroyed: boolean): void; export function _onFragmentHidden(fragment: any, isBack: boolean, destroyed: boolean): void;

View File

@ -1,4 +1,4 @@
import {View} from "ui/core/view"; import { View } from "ui/core/view";
import * as utils from "utils/utils"; import * as utils from "utils/utils";
import getter = utils.ios.getter; import getter = utils.ios.getter;

View File

@ -1,16 +1,7 @@
declare module "utils/utils" { declare module "utils/utils" {
import * as colorModule from "color";
export var RESOURCE_PREFIX: string; export var RESOURCE_PREFIX: string;
//@private //@private
/**
* Used by various android event listener implementations
*/
interface Owned {
owner: any;
}
/** /**
* Used to cache and restore Android views' layer type, i.e. android.view.View.getLayerType and android.view.View.setLayerType. * Used to cache and restore Android views' layer type, i.e. android.view.View.getLayerType and android.view.View.setLayerType.
*/ */
@ -159,17 +150,6 @@
*/ */
export function getter<T>(_this: any, propertyValue: T | {(): T}): T; export function getter<T>(_this: any, propertyValue: T | {(): T}): T;
// Common properties between UILabel, UITextView and UITextField
export interface TextUIView {
font: any;
textAlignment: number;
textColor: any;
text: string;
attributedText: any;
lineBreakMode: number;
numberOfLines: number;
}
/** /**
* Utility module dealing with some iOS collections. * Utility module dealing with some iOS collections.
*/ */
@ -186,15 +166,11 @@
export function nsArrayToJSArray(a: any): string[]; export function nsArrayToJSArray(a: any): string[];
} }
/**
* Gets NativeScript color from [UIColor](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIColor_Class/).
* @param uiColor - UIColor instance used to create a NativeScript color.
*/
export function getColor(uiColor: any /* UIColor */): colorModule.Color;
/** /**
* Gets an information about if current mode is Landscape. * Gets an information about if current mode is Landscape.
*/ */
export function isLandscape(): boolean; export function isLandscape(): boolean;
/** /**
* Gets the iOS device major version (for 8.1 will return 8). * Gets the iOS device major version (for 8.1 will return 8).
*/ */
@ -240,7 +216,7 @@
* Converts string value to number or boolean. * Converts string value to number or boolean.
* @param value The original value. * @param value The original value.
*/ */
export function convertString(value: any): any export function convertString(value: string): boolean | number;
/** /**
* Sorts an array by using merge sort algoritm (which ensures stable sort since the built-in Array.sort() does not promise a stable sort). * Sorts an array by using merge sort algoritm (which ensures stable sort since the built-in Array.sort() does not promise a stable sort).

View File

@ -1,5 +1,4 @@
import { Color } from "color"; import * as fsModule from "file-system";
import * as fsModule from "file-system";
import { import {
write as traceWrite, categories as traceCategories, messageType as traceMessageType write as traceWrite, categories as traceCategories, messageType as traceMessageType
} from "trace"; } from "trace";
@ -58,21 +57,6 @@ export module ios {
} }
} }
export function getColor(uiColor: UIColor): Color {
var redRef = new interop.Reference<number>();
var greenRef = new interop.Reference<number>();
var blueRef = new interop.Reference<number>();
var alphaRef = new interop.Reference<number>();
uiColor.getRedGreenBlueAlpha(redRef, greenRef, blueRef, alphaRef);
var red = redRef.value * 255;
var green = greenRef.value * 255;
var blue = blueRef.value * 255;
var alpha = alphaRef.value * 255;
return new Color(alpha, red, green, blue);
}
export function isLandscape(): boolean { export function isLandscape(): boolean {
var device = getter(UIDevice, UIDevice.currentDevice); var device = getter(UIDevice, UIDevice.currentDevice);
var statusBarOrientation = getter(UIApplication, UIApplication.sharedApplication).statusBarOrientation; var statusBarOrientation = getter(UIApplication, UIApplication.sharedApplication).statusBarOrientation;