Snapshot refactorings, which mainly wraps Android extends within inner functions so that they are evaluated at runtime, when needed. Also some refactoring preventing circular requires.

This commit is contained in:
atanasovg
2016-01-19 17:52:33 +02:00
parent 935939bb51
commit fbc612610f
31 changed files with 943 additions and 721 deletions

View File

@ -981,6 +981,8 @@
<TypeScriptCompile Include="ui\utils.ios.ts">
<DependentUpon>utils.d.ts</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="utils\debug.d.ts" />
<TypeScriptCompile Include="utils\debug.ts" />
<TypeScriptCompile Include="utils\module-merge.ts" />
<TypeScriptCompile Include="utils\utils.android.ts">
<DependentUpon>utils.d.ts</DependentUpon>
@ -2139,7 +2141,7 @@
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>0</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:3128/</IISUrl>
<IISUrl>http://localhost:60276/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>

View File

@ -1,5 +1,4 @@

export var checkKey = function(key: string) : void {
export var checkKey = function(key: string) : void {
if ("string" !== typeof key) {
throw new Error("key: '" + key + "' must be a string");
}

View File

@ -1,16 +1,26 @@
import Common = require("./application-settings-common");
import common = require("./application-settings-common");
import utils = require("utils/utils");
var sharedPreferences = utils.ad.getApplicationContext().getSharedPreferences("prefs.db", 0);
var sharedPreferences;
function ensureSharedPreferences() {
if (!sharedPreferences) {
sharedPreferences = utils.ad.getApplicationContext().getSharedPreferences("prefs.db", 0);
}
}
function verify(key: string) {
common.checkKey(key);
ensureSharedPreferences();
}
export var hasKey = function (key: string): boolean {
Common.checkKey(key);
verify(key);
return sharedPreferences.contains(key);
}
// getters
export var getBoolean = function (key: string, defaultValue?: boolean): boolean {
Common.checkKey(key);
verify(key);
if (hasKey(key)) {
return sharedPreferences.getBoolean(key, false);
}
@ -18,7 +28,7 @@ export var getBoolean = function (key: string, defaultValue?: boolean): boolean
}
export var getString = function (key: string, defaultValue?: string): string {
Common.checkKey(key);
verify(key);
if (hasKey(key)) {
return sharedPreferences.getString(key, "");
}
@ -26,7 +36,7 @@ export var getString = function (key: string, defaultValue?: string): string {
}
export var getNumber = function (key: string, defaultValue?: number): number {
Common.checkKey(key);
verify(key);
if (hasKey(key)) {
return sharedPreferences.getFloat(key, float(0.0));
}
@ -35,31 +45,31 @@ export var getNumber = function (key: string, defaultValue?: number): number {
// setters
export var setBoolean = function (key: string, value: boolean): void {
Common.checkKey(key);
Common.ensureValidValue(value, "boolean");
verify(key);
common.ensureValidValue(value, "boolean");
var editor = sharedPreferences.edit();
editor.putBoolean(key, value);
editor.commit();
}
export var setString = function (key: string, value: string): void {
Common.checkKey(key);
Common.ensureValidValue(value, "string");
verify(key);
common.ensureValidValue(value, "string");
var editor = sharedPreferences.edit();
editor.putString(key, value);
editor.commit();
}
export var setNumber = function (key: string, value: number): void {
Common.checkKey(key);
Common.ensureValidValue(value, "number");
verify(key);
common.ensureValidValue(value, "number");
var editor = sharedPreferences.edit();
editor.putFloat(key, float(value));
editor.commit();
}
export var remove = function (key: string): void {
Common.checkKey(key);
verify(key);
var editor = sharedPreferences.edit();
editor.remove(key);
editor.commit();

View File

@ -11,7 +11,7 @@ var typedExports: typeof definition = exports;
// We are using the exports object for the common events since we merge the appModule with this module's exports, which is what users will receive when require("application") is called;
// TODO: This is kind of hacky and is "pure JS in TypeScript"
var initEvents = function () {
function initEvents() {
// TODO: Verify whether the logic for triggerring application-wide events based on Activity callbacks is working properly
var lifecycleCallbacks = new android.app.Application.ActivityLifecycleCallbacks({
onActivityCreated: function (activity: any, bundle: any) {
@ -152,17 +152,6 @@ var initEvents = function () {
return lifecycleCallbacks;
}
app.init({
getActivity: function (activity: android.app.Activity) {
var intent = activity.getIntent()
return androidApp.getActivity(intent);
},
onCreate: function () {
androidApp.init(this);
}
});
export class AndroidApplication extends observable.Observable implements definition.AndroidApplication {
public static activityCreatedEvent = "activityCreated";
public static activityDestroyedEvent = "activityDestroyed";
@ -264,9 +253,10 @@ export class AndroidApplication extends observable.Observable implements definit
}
public registerBroadcastReceiver(intentFilter: string, onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void) {
ensureBroadCastReceiverClass();
var that = this;
var registerFunc = function (context: android.content.Context) {
var receiver = new BroadcastReceiver(onReceiveCallback);
var receiver = new BroadcastReceiverClass(onReceiveCallback);
context.registerReceiver(receiver, new android.content.IntentFilter(intentFilter));
that._registeredReceivers[intentFilter] = receiver;
}
@ -289,20 +279,29 @@ export class AndroidApplication extends observable.Observable implements definit
}
}
class BroadcastReceiver extends android.content.BroadcastReceiver {
private _onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void;
constructor(onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void) {
super();
this._onReceiveCallback = onReceiveCallback;
return global.__native(this);
var BroadcastReceiverClass;
function ensureBroadCastReceiverClass() {
if (BroadcastReceiverClass) {
return;
}
public onReceive(context: android.content.Context, intent: android.content.Intent) {
if (this._onReceiveCallback) {
this._onReceiveCallback(context, intent);
class BroadcastReceiver extends android.content.BroadcastReceiver {
private _onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void;
constructor(onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void) {
super();
this._onReceiveCallback = onReceiveCallback;
return global.__native(this);
}
public onReceive(context: android.content.Context, intent: android.content.Intent) {
if (this._onReceiveCallback) {
this._onReceiveCallback(context, intent);
}
}
}
BroadcastReceiverClass = BroadcastReceiver;
}
global.__onUncaughtError = function (error: definition.NativeScriptError) {
@ -320,10 +319,29 @@ function loadCss() {
typedExports.cssSelectorsCache = typedExports.loadCss(typedExports.cssFile);
}
export function start(entry?: frame.NavigationEntry) {
if (entry) {
var started = false;
export function start (entry?: frame.NavigationEntry) {
if (started) {
throw new Error("Application is already started.");
}
started = true;
if (entry) {
typedExports.mainEntry = entry;
}
// this should be the first call, to avoid issues when someone accesses the Application singleton prior to extending its onCreate method
app.init({
getActivity: function (activity: android.app.Activity) {
var intent = activity.getIntent()
return androidApp.getActivity(intent);
},
onCreate: function () {
androidApp.init(this);
}
});
loadCss();
}

View File

@ -3,7 +3,7 @@ import fs = require("file-system");
import types = require("utils/types");
import trace = require("trace");
import platform = require("platform");
import application = require("application");
import * as appModule from "application";
var MIN_WH: string = "minWH";
var MIN_W: string = "minW";
@ -225,7 +225,8 @@ var resolverInstance: FileNameResolver;
export function resolveFileName(path: string, ext: string): string {
if (!appEventAttached) {
application.on(application.orientationChangedEvent, (data) => {
var app: typeof appModule = require("application");
app.on(app.orientationChangedEvent, (data) => {
resolverInstance = undefined;
});
appEventAttached = true;

View File

@ -3,7 +3,7 @@ import utils = require("utils/utils");
import * as typesModule from "utils/types";
export class FileSystemAccess {
private _pathSeparator = java.io.File.separator.toString();
private _pathSeparator = "/";
public getLastModified(path: string): Date {
var javaFile = new java.io.File(path);

View File

@ -1,4 +1,5 @@
import file_access_module = require("file-system/file-system-access");
import * as utilsModule from "utils/utils";
// The FileSystemAccess implementation, used through all the APIs.
var fileAccess;
@ -442,17 +443,10 @@ export module knownFolders {
export var currentApp = function (): Folder {
if (!_app) {
const currentDir = __dirname;
const tnsModulesIndex = currentDir.indexOf("/tns_modules");
// Module not hosted in ~/tns_modules when bundled. Use current dir.
let appPath = currentDir;
if (tnsModulesIndex !== -1) {
// Strip part after tns_modules to obtain app root
appPath = currentDir.substring(0, tnsModulesIndex);
}
var utils: typeof utilsModule = require("utils/utils");
var filesDir = utils.ad.getApplicationContext().getFilesDir().getCanonicalPath();
_app = new Folder();
_app[pathProperty] = appPath;
_app[pathProperty] = filesDir + "/app/";
_app[isKnownProperty] = true;
}

View File

@ -29,7 +29,12 @@ function doFrame(currentTimeMillis: number) {
}
}
var native = new fpsNative.FPSCallback(doFrame);
var native;
function ensureNative() {
if (!native) {
native = new fpsNative.FPSCallback(doFrame);
}
}
export function reset() {
_minFps = 1000;
@ -38,6 +43,10 @@ export function reset() {
}
export function running(): boolean {
if (!native) {
return false;
}
return native.running;
}
@ -46,10 +55,15 @@ export function minFps(): number {
}
export function start() {
ensureNative();
native.start();
}
export function stop() {
if (!native) {
return;
}
native.stop();
reset();
}

View File

@ -28,7 +28,7 @@ global.loadModule = function(name: string): any {
global.registerModule("timer", () => require("timer"));
global.registerModule("ui/dialogs", () => require("ui/dialogs"));
global.registerModule("../xhr/xhr", () => require("../xhr/xhr"));
global.registerModule("xhr", () => require("xhr"));
global.registerModule("fetch", () => require("fetch"));
const __tnsGlobalMergedModules = new Map<string, boolean>();
@ -61,8 +61,8 @@ registerOnGlobalContext("clearInterval", "timer");
registerOnGlobalContext("alert", "ui/dialogs");
registerOnGlobalContext("confirm", "ui/dialogs");
registerOnGlobalContext("prompt", "ui/dialogs");
registerOnGlobalContext("XMLHttpRequest", "../xhr/xhr");
registerOnGlobalContext("FormData", "../xhr/xhr");
registerOnGlobalContext("XMLHttpRequest", "xhr");
registerOnGlobalContext("FormData", "xhr");
registerOnGlobalContext("fetch", "fetch");
import platform = require("platform");

View File

@ -12,12 +12,19 @@ import http = require("http");
var requestIdCounter = 0;
var pendingRequests = {};
var completeCallback = new com.tns.Async.CompleteCallback({
onComplete: function (result: any, context: any) {
// as a context we will receive the id of the request
onRequestComplete(context, result);
var completeCallback;
function ensureCompleteCallback() {
if (completeCallback) {
return;
}
});
completeCallback = new com.tns.Async.CompleteCallback({
onComplete: function (result: any, context: any) {
// as a context we will receive the id of the request
onRequestComplete(context, result);
}
});
}
function onRequestComplete(requestId: number, result: com.tns.Async.Http.RequestResult) {
var callbacks = pendingRequests[requestId];
@ -132,6 +139,7 @@ export function request(options: http.HttpRequestOptions): Promise<http.HttpResp
};
pendingRequests[requestIdCounter] = callbacks;
ensureCompleteCallback();
//make the actual async call
com.tns.Async.Http.MakeRequest(javaOptions, completeCallback, new java.lang.Integer(requestIdCounter));

View File

@ -60,7 +60,7 @@ export class LocationManager implements locationModule.LocationManager {
}
private static locationFromAndroidLocation(androidLocation: android.location.Location): locationModule.Location {
var location = new locationModule.Location();
var location = new common.Location();
location.latitude = androidLocation.getLatitude();
location.longitude = androidLocation.getLongitude();
location.altitude = androidLocation.getAltitude();

View File

@ -226,7 +226,7 @@ export class FormattedString extends observable.Observable implements definition
public static addFormattedStringToView(view: definition.FormattedStringView, name: string, value: any): void {
if(name === CHILD_SPAN) {
if (!view.formattedText) {
view.formattedText = new definition.FormattedString();
view.formattedText = new FormattedString();
}
view.formattedText.spans.push(value);
}

View File

@ -6,43 +6,52 @@ import fontModule = require("ui/styling/font");
global.moduleMerge(spanCommon, exports);
export class CustomTypefaceSpan extends android.text.style.TypefaceSpan {
private typeface: any;
constructor(family: string, typeface: any) {
super(family);
this.typeface = typeface;
return global.__native(this);
var CustomTypefaceSpanClass;
function ensureCustomTypefaceSpanClass() {
if (CustomTypefaceSpanClass) {
return;
}
public updateDrawState(ds: any): void {
CustomTypefaceSpan.applyCustomTypeFace(ds, this.typeface);
}
class CustomTypefaceSpan extends android.text.style.TypefaceSpan {
private typeface: any;
public updateMeasureState(paint: any): void {
CustomTypefaceSpan.applyCustomTypeFace(paint, this.typeface);
}
private static applyCustomTypeFace(paint: any, tf: any) {
let oldStyle;
let old = paint.getTypeface();
if (old === null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
constructor(family: string, typeface: any) {
super(family);
this.typeface = typeface;
return global.__native(this);
}
let fake = oldStyle & ~tf.getStyle();
if ((fake & android.graphics.Typeface.BOLD) !== 0) {
paint.setFakeBoldText(true);
public updateDrawState(ds: any): void {
CustomTypefaceSpan.applyCustomTypeFace(ds, this.typeface);
}
if ((fake & android.graphics.Typeface.ITALIC) !== 0) {
paint.setTextSkewX(-0.25);
public updateMeasureState(paint: any): void {
CustomTypefaceSpan.applyCustomTypeFace(paint, this.typeface);
}
paint.setTypeface(tf);
private static applyCustomTypeFace(paint: any, tf: any) {
let oldStyle;
let old = paint.getTypeface();
if (old === null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
}
let fake = oldStyle & ~tf.getStyle();
if ((fake & android.graphics.Typeface.BOLD) !== 0) {
paint.setFakeBoldText(true);
}
if ((fake & android.graphics.Typeface.ITALIC) !== 0) {
paint.setTextSkewX(-0.25);
}
paint.setTypeface(tf);
}
}
CustomTypefaceSpanClass = CustomTypefaceSpan;
}
export class Span extends spanCommon.Span {
@ -54,7 +63,8 @@ export class Span extends spanCommon.Span {
0,
(realFontAttributes & enums.FontAttributes.Italic) ? enums.FontStyle.italic : enums.FontStyle.normal,
(realFontAttributes & enums.FontAttributes.Bold) ? enums.FontWeight.bold : enums.FontWeight.normal);
let typefaceSpan = new CustomTypefaceSpan(realFontFamily, font.getAndroidTypeface());
ensureCustomTypefaceSpanClass();
let typefaceSpan = new CustomTypefaceSpanClass(realFontFamily, font.getAndroidTypeface());
this.spanModifiers.push(typefaceSpan);
}
var realFontSize = this.fontSize ||

View File

@ -8,8 +8,19 @@ import enums = require("ui/enums");
global.moduleMerge(common, exports);
var floatType = java.lang.Float.class.getField("TYPE").get(null);
var argbEvaluator = new android.animation.ArgbEvaluator();
var floatType;
function ensureFloatType() {
if (!floatType) {
floatType = java.lang.Float.class.getField("TYPE").get(null);
}
}
var argbEvaluator;
function ensureArgbEvaluator() {
if (!argbEvaluator) {
argbEvaluator = new android.animation.ArgbEvaluator();
}
}
var keyPrefix = "ui.animation.";
var propertyKeys = {};
@ -154,6 +165,8 @@ export class Animation extends common.Animation implements definition.Animation
}
}
}
ensureFloatType();
switch (propertyAnimation.property) {
@ -167,6 +180,7 @@ export class Animation extends common.Animation implements definition.Animation
break;
case common.Properties.backgroundColor:
ensureArgbEvaluator();
originalValue1 = nativeView.getBackground();
nativeArray = java.lang.reflect.Array.newInstance(java.lang.Object.class, 2);
nativeArray[0] = propertyAnimation.target.backgroundColor ? java.lang.Integer.valueOf((<color.Color>propertyAnimation.target.backgroundColor).argb) : java.lang.Integer.valueOf(-1);

View File

@ -131,7 +131,7 @@ export function prompt(arg: any): Promise<dialogs.PromptResult> {
title: dialogsCommon.PROMPT,
okButtonText: dialogsCommon.OK,
cancelButtonText: dialogsCommon.CANCEL,
inputType: dialogs.inputType.text,
inputType: dialogsCommon.inputType.text,
};
if (arguments.length === 1) {
@ -155,7 +155,7 @@ export function prompt(arg: any): Promise<dialogs.PromptResult> {
var input = new android.widget.EditText(appmodule.android.currentContext);
if (options && options.inputType === dialogs.inputType.password) {
if (options && options.inputType === dialogsCommon.inputType.password) {
input.setInputType(android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD);
}

View File

@ -51,7 +51,7 @@ export class EditableTextBase extends common.EditableTextBase {
owner._dirtyTextAccumulator = editable.toString();
break;
case enums.UpdateTextTrigger.textChanged:
owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, editable.toString());
owner._onPropertyChangedFromNative(EditableTextBase.textProperty, editable.toString());
break;
default:
throw new Error("Invalid updateTextTrigger: " + owner.updateTextTrigger);
@ -70,7 +70,7 @@ export class EditableTextBase extends common.EditableTextBase {
if (!hasFocus) {
if (owner._dirtyTextAccumulator) {
owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, owner._dirtyTextAccumulator);
owner._onPropertyChangedFromNative(EditableTextBase.textProperty, owner._dirtyTextAccumulator);
owner._dirtyTextAccumulator = undefined;
}

View File

@ -21,62 +21,69 @@ var activityInitialized = false;
var navDepth = -1;
var PageFragmentBody = (<any>android.app.Fragment).extend({
onCreate: function (savedInstanceState: android.os.Bundle) {
trace.write(`PageFragmentBody.onCreate(${savedInstanceState})`, trace.categories.NativeLifecycle);
this.super.onCreate(savedInstanceState);
this.super.setHasOptionsMenu(true);
},
onCreateView: function (inflater: android.view.LayoutInflater, container: android.view.ViewGroup, savedInstanceState: android.os.Bundle): android.view.View {
var entry = this.entry;
var page = entry.resolvedPage;
trace.write(`PageFragmentBody.onCreateView(${inflater}, ${page}, ${savedInstanceState})`, trace.categories.NativeLifecycle);
if (savedInstanceState && savedInstanceState.getBoolean(HIDDEN, false)) {
this.super.getFragmentManager().beginTransaction().hide(this).commit();
page._onAttached(this.getActivity());
}
else {
onFragmentShown(this);
}
return page._nativeView;
},
onHiddenChanged: function (hidden: boolean) {
trace.write(`PageFragmentBody.onHiddenChanged(${hidden})`, trace.categories.NativeLifecycle);
this.super.onHiddenChanged(hidden);
if (hidden) {
onFragmentHidden(this);
}
else {
onFragmentShown(this);
}
},
onSaveInstanceState: function (outState: android.os.Bundle) {
trace.write(`PageFragmentBody.onSaveInstanceState(${outState})`, trace.categories.NativeLifecycle);
this.super.onSaveInstanceState(outState);
if (this.isHidden()) {
outState.putBoolean(HIDDEN, true);
}
},
onDestroyView: function () {
trace.write(`PageFragmentBody.onDestroyView()`, trace.categories.NativeLifecycle);
this.super.onDestroyView();
onFragmentHidden(this);
},
onDestroy: function () {
trace.write(`PageFragmentBody.onDestroy()`, trace.categories.NativeLifecycle);
this.super.onDestroy();
var utils: typeof utilsModule = require("utils/utils");
utils.GC();
var FragmentClass;
function ensureFragmentClass() {
if (FragmentClass) {
return;
}
});
FragmentClass = (<any>android.app.Fragment).extend({
onCreate: function (savedInstanceState: android.os.Bundle) {
trace.write(`PageFragmentBody.onCreate(${savedInstanceState})`, trace.categories.NativeLifecycle);
this.super.onCreate(savedInstanceState);
this.super.setHasOptionsMenu(true);
},
onCreateView: function (inflater: android.view.LayoutInflater, container: android.view.ViewGroup, savedInstanceState: android.os.Bundle): android.view.View {
var entry = this.entry;
var page = entry.resolvedPage;
trace.write(`PageFragmentBody.onCreateView(${inflater}, ${page}, ${savedInstanceState})`, trace.categories.NativeLifecycle);
if (savedInstanceState && savedInstanceState.getBoolean(HIDDEN, false)) {
this.super.getFragmentManager().beginTransaction().hide(this).commit();
page._onAttached(this.getActivity());
}
else {
onFragmentShown(this);
}
return page._nativeView;
},
onHiddenChanged: function (hidden: boolean) {
trace.write(`PageFragmentBody.onHiddenChanged(${hidden})`, trace.categories.NativeLifecycle);
this.super.onHiddenChanged(hidden);
if (hidden) {
onFragmentHidden(this);
}
else {
onFragmentShown(this);
}
},
onSaveInstanceState: function (outState: android.os.Bundle) {
trace.write(`PageFragmentBody.onSaveInstanceState(${outState})`, trace.categories.NativeLifecycle);
this.super.onSaveInstanceState(outState);
if (this.isHidden()) {
outState.putBoolean(HIDDEN, true);
}
},
onDestroyView: function () {
trace.write(`PageFragmentBody.onDestroyView()`, trace.categories.NativeLifecycle);
this.super.onDestroyView();
onFragmentHidden(this);
},
onDestroy: function () {
trace.write(`PageFragmentBody.onDestroy()`, trace.categories.NativeLifecycle);
this.super.onDestroy();
var utils: typeof utilsModule = require("utils/utils");
utils.GC();
}
});
}
function onFragmentShown(fragment) {
trace.write(`onFragmentShown(${fragment.toString()})`, trace.categories.NativeLifecycle);
@ -215,7 +222,8 @@ export class Frame extends frameCommon.Frame {
var fragmentTransaction = manager.beginTransaction();
var newFragmentTag = "fragment" + navDepth;
var newFragment = new PageFragmentBody();
ensureFragmentClass();
var newFragment = new FragmentClass();
newFragment.frame = this;
newFragment.entry = backstackEntry;

View File

@ -78,15 +78,18 @@ export class GesturesObserver extends common.GesturesObserver {
this._detach();
if (type & definition.GestureTypes.tap || type & definition.GestureTypes.doubleTap || type & definition.GestureTypes.longPress) {
this._simpleGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListener(this, this.target, type));
ensureTapAndDoubleTapGestureListenerClass();
this._simpleGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListenerClass(this, this.target, type));
}
if (type & definition.GestureTypes.pinch) {
this._scaleGestureDetector = new android.view.ScaleGestureDetector(target._context, new PinchGestureListener(this, this.target));
ensurePinchGestureListenerClass();
this._scaleGestureDetector = new android.view.ScaleGestureDetector(target._context, new PinchGestureListenerClass(this, this.target));
}
if (type & definition.GestureTypes.swipe) {
this._swipeGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new SwipeGestureListener(this, this.target));
ensureSwipeGestureListenerClass();
this._swipeGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new SwipeGestureListenerClass(this, this.target));
}
if (type & definition.GestureTypes.pan) {
@ -179,46 +182,55 @@ function _executeCallback(observer: GesturesObserver, args: definition.GestureEv
}
}
class TapAndDoubleTapGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
private _observer: GesturesObserver;
private _target: view.View;
private _type: number;
constructor(observer: GesturesObserver, target: view.View, type: number) {
super();
this._observer = observer;
this._target = target;
this._type = type;
return global.__native(this);
var TapAndDoubleTapGestureListenerClass;
function ensureTapAndDoubleTapGestureListenerClass() {
if (TapAndDoubleTapGestureListenerClass) {
return;
}
public onSingleTapUp(motionEvent: android.view.MotionEvent): boolean {
if (this._type & definition.GestureTypes.tap) {
var args = _getArgs(definition.GestureTypes.tap, this._target, motionEvent);
_executeCallback(this._observer, args);
class TapAndDoubleTapGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
private _observer: GesturesObserver;
private _target: view.View;
private _type: number;
constructor(observer: GesturesObserver, target: view.View, type: number) {
super();
this._observer = observer;
this._target = target;
this._type = type;
return global.__native(this);
}
return true;
}
public onDoubleTap(motionEvent: android.view.MotionEvent): boolean {
if (this._type & definition.GestureTypes.doubleTap) {
var args = _getArgs(definition.GestureTypes.doubleTap, this._target, motionEvent);
_executeCallback(this._observer, args);
public onSingleTapUp(motionEvent: android.view.MotionEvent): boolean {
if (this._type & definition.GestureTypes.tap) {
var args = _getArgs(definition.GestureTypes.tap, this._target, motionEvent);
_executeCallback(this._observer, args);
}
return true;
}
return true;
}
public onDown(motionEvent: android.view.MotionEvent): boolean {
return true;
}
public onDoubleTap(motionEvent: android.view.MotionEvent): boolean {
if (this._type & definition.GestureTypes.doubleTap) {
var args = _getArgs(definition.GestureTypes.doubleTap, this._target, motionEvent);
_executeCallback(this._observer, args);
}
return true;
}
public onLongPress(motionEvent: android.view.MotionEvent): void {
if (this._type & definition.GestureTypes.longPress) {
var args = _getArgs(definition.GestureTypes.longPress, this._target, motionEvent);
_executeCallback(this._observer, args);
public onDown(motionEvent: android.view.MotionEvent): boolean {
return true;
}
public onLongPress(motionEvent: android.view.MotionEvent): void {
if (this._type & definition.GestureTypes.longPress) {
var args = _getArgs(definition.GestureTypes.longPress, this._target, motionEvent);
_executeCallback(this._observer, args);
}
}
}
TapAndDoubleTapGestureListenerClass = TapAndDoubleTapGestureListener;
}
class PinchGestureEventData implements definition.PinchGestureEventData {
@ -243,135 +255,153 @@ class PinchGestureEventData implements definition.PinchGestureEventData {
}
}
class PinchGestureListener extends android.view.ScaleGestureDetector.SimpleOnScaleGestureListener {
private _observer: GesturesObserver;
private _target: view.View;
private _scale: number;
private _density: number;
constructor(observer: GesturesObserver, target: view.View) {
super();
this._observer = observer;
this._target = target;
this._density = utils.layout.getDisplayDensity();
return global.__native(this);
var PinchGestureListenerClass;
function ensurePinchGestureListenerClass() {
if (PinchGestureListenerClass) {
return;
}
public onScaleBegin(detector: android.view.ScaleGestureDetector): boolean {
this._scale = detector.getScaleFactor();
class PinchGestureListener extends android.view.ScaleGestureDetector.SimpleOnScaleGestureListener {
private _observer: GesturesObserver;
private _target: view.View;
private _scale: number;
private _density: number;
var args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
common.GestureStateTypes.began);
constructor(observer: GesturesObserver, target: view.View) {
super();
_executeCallback(this._observer, args);
this._observer = observer;
this._target = target;
this._density = utils.layout.getDisplayDensity();
return true;
}
public onScale(detector: android.view.ScaleGestureDetector): boolean {
this._scale *= detector.getScaleFactor();
var args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
common.GestureStateTypes.changed);
_executeCallback(this._observer, args);
return true;
}
public onScaleEnd(detector: android.view.ScaleGestureDetector): void {
this._scale *= detector.getScaleFactor();
var args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
common.GestureStateTypes.ended);
_executeCallback(this._observer, args);
}
}
class SwipeGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
private _observer: GesturesObserver;
private _target: view.View;
constructor(observer: GesturesObserver, target: view.View) {
super();
this._observer = observer;
this._target = target;
return global.__native(this);
}
public onDown(motionEvent: android.view.MotionEvent): boolean {
return true;
}
public onFling(initialEvent: android.view.MotionEvent, currentEvent: android.view.MotionEvent, velocityX: number, velocityY: number): boolean {
var result = false;
var args: definition.SwipeGestureEventData;
try {
var deltaY = currentEvent.getY() - initialEvent.getY();
var deltaX = currentEvent.getX() - initialEvent.getX();
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (Math.abs(deltaX) > SWIPE_THRESHOLD
&& Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (deltaX > 0) {
args = _getSwipeArgs(definition.SwipeDirection.right, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
} else {
args = _getSwipeArgs(definition.SwipeDirection.left, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
}
}
} else {
if (Math.abs(deltaY) > SWIPE_THRESHOLD
&& Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (deltaY > 0) {
args = _getSwipeArgs(definition.SwipeDirection.down, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
} else {
args = _getSwipeArgs(definition.SwipeDirection.up, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
}
}
}
} catch (ex) {
//
return global.__native(this);
}
return result;
public onScaleBegin(detector: android.view.ScaleGestureDetector): boolean {
this._scale = detector.getScaleFactor();
var args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
common.GestureStateTypes.began);
_executeCallback(this._observer, args);
return true;
}
public onScale(detector: android.view.ScaleGestureDetector): boolean {
this._scale *= detector.getScaleFactor();
var args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
common.GestureStateTypes.changed);
_executeCallback(this._observer, args);
return true;
}
public onScaleEnd(detector: android.view.ScaleGestureDetector): void {
this._scale *= detector.getScaleFactor();
var args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
common.GestureStateTypes.ended);
_executeCallback(this._observer, args);
}
}
PinchGestureListenerClass = PinchGestureListener;
}
var SwipeGestureListenerClass;
function ensureSwipeGestureListenerClass() {
if (SwipeGestureListenerClass) {
return;
}
class SwipeGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
private _observer: GesturesObserver;
private _target: view.View;
constructor(observer: GesturesObserver, target: view.View) {
super();
this._observer = observer;
this._target = target;
return global.__native(this);
}
public onDown(motionEvent: android.view.MotionEvent): boolean {
return true;
}
public onFling(initialEvent: android.view.MotionEvent, currentEvent: android.view.MotionEvent, velocityX: number, velocityY: number): boolean {
var result = false;
var args: definition.SwipeGestureEventData;
try {
var deltaY = currentEvent.getY() - initialEvent.getY();
var deltaX = currentEvent.getX() - initialEvent.getX();
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (Math.abs(deltaX) > SWIPE_THRESHOLD
&& Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (deltaX > 0) {
args = _getSwipeArgs(definition.SwipeDirection.right, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
} else {
args = _getSwipeArgs(definition.SwipeDirection.left, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
}
}
} else {
if (Math.abs(deltaY) > SWIPE_THRESHOLD
&& Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (deltaY > 0) {
args = _getSwipeArgs(definition.SwipeDirection.down, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
} else {
args = _getSwipeArgs(definition.SwipeDirection.up, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
}
}
}
} catch (ex) {
//
}
return result;
}
}
SwipeGestureListenerClass = SwipeGestureListener;
}
class CustomPanGestureDetector {

View File

@ -42,7 +42,5 @@ export class HtmlView extends common.HtmlView {
// This makes the html <a href...> vwork
this._android.setLinksClickable(true);
this._android.setMovementMethod(android.text.method.LinkMovementMethod.getInstance());
}
}

View File

@ -1,35 +1,45 @@
import common = require("./image-cache-common");
class LruBitmapCache extends android.util.LruCache<string, android.graphics.Bitmap> {
constructor(cacheSize: number) {
super(cacheSize);
return global.__native(this);
var LruBitmapCacheClass;
function ensureLruBitmapCacheClass() {
if (LruBitmapCacheClass) {
return;
}
protected sizeOf(key: string, bitmap: android.graphics.Bitmap): number {
// The cache size will be measured in kilobytes rather than
// number of items.
var result = Math.round(bitmap.getByteCount() / 1024);
//console.log("sizeOf key: " + result);
return result;
}
class LruBitmapCache extends android.util.LruCache<string, android.graphics.Bitmap> {
constructor(cacheSize: number) {
super(cacheSize);
return global.__native(this);
}
//protected entryRemoved(evicted: boolean, key: string, oldValue: android.graphics.Bitmap, newValue: android.graphics.Bitmap): void {
// console.log("entryRemoved("+evicted+", "+key+", "+oldValue+", "+newValue+")");
//}
};
protected sizeOf(key: string, bitmap: android.graphics.Bitmap): number {
// The cache size will be measured in kilobytes rather than
// number of items.
var result = Math.round(bitmap.getByteCount() / 1024);
//console.log("sizeOf key: " + result);
return result;
}
//protected entryRemoved(evicted: boolean, key: string, oldValue: android.graphics.Bitmap, newValue: android.graphics.Bitmap): void {
// console.log("entryRemoved("+evicted+", "+key+", "+oldValue+", "+newValue+")");
//}
};
LruBitmapCacheClass = LruBitmapCache;
}
export class Cache extends common.Cache {
private _callback: any;
private _cache: LruBitmapCache;
private _cache;
constructor() {
super();
ensureLruBitmapCacheClass();
var maxMemory = java.lang.Runtime.getRuntime().maxMemory() / 1024;
var cacheSize = maxMemory / 8;
//console.log("cacheSize: " + cacheSize);
this._cache = new LruBitmapCache(cacheSize);
this._cache = new LruBitmapCacheClass(cacheSize);
var that = new WeakRef(this);
this._callback = new (<any>com).tns.Async.CompleteCallback({

View File

@ -6,17 +6,24 @@ import * as utilsModule from "utils/utils";
var OWNER = "_owner";
var NativeViewGroup = (<any>android.view.ViewGroup).extend({
onMeasure: function (widthMeasureSpec, heightMeasureSpec) {
var owner: view.View = this[OWNER];
owner.onMeasure(widthMeasureSpec, heightMeasureSpec);
this.setMeasuredDimension(owner.getMeasuredWidth(), owner.getMeasuredHeight());
},
onLayout: function (changed: boolean, left: number, top: number, right: number, bottom: number): void {
var owner: view.View = this[OWNER];
owner.onLayout(left, top, right, bottom);
var NativeViewGroupClass;
function ensureNativeViewGroupClass() {
if (NativeViewGroupClass) {
return;
}
});
NativeViewGroupClass = (<any>android.view.ViewGroup).extend({
onMeasure: function (widthMeasureSpec, heightMeasureSpec) {
var owner: view.View = this[OWNER];
owner.onMeasure(widthMeasureSpec, heightMeasureSpec);
this.setMeasuredDimension(owner.getMeasuredWidth(), owner.getMeasuredHeight());
},
onLayout: function (changed: boolean, left: number, top: number, right: number, bottom: number): void {
var owner: view.View = this[OWNER];
owner.onLayout(left, top, right, bottom);
}
});
}
export class Layout extends layoutBase.LayoutBase implements definition.Layout {
private _viewGroup: android.view.ViewGroup;
@ -30,7 +37,8 @@ export class Layout extends layoutBase.LayoutBase implements definition.Layout {
}
public _createUI() {
this._viewGroup = new NativeViewGroup(this._context);
ensureNativeViewGroupClass();
this._viewGroup = new NativeViewGroupClass(this._context);
this._viewGroup[OWNER] = this;
}

View File

@ -48,7 +48,8 @@ export class ListView extends common.ListView {
}
this._android.setId(this._androidViewId);
this.android.setAdapter(new ListViewAdapter(this));
ensureListViewAdapterClass();
this.android.setAdapter(new ListViewAdapterClass(this));
var that = new WeakRef(this);
@ -102,7 +103,7 @@ export class ListView extends common.ListView {
return;
}
(<ListViewAdapter>this.android.getAdapter()).notifyDataSetChanged();
(<android.widget.BaseAdapter>this.android.getAdapter()).notifyDataSetChanged();
}
public scrollToIndex(index: number) {
@ -158,83 +159,91 @@ export class ListView extends common.ListView {
}
}
class ListViewAdapter extends android.widget.BaseAdapter {
private _listView: ListView;
constructor(listView: ListView) {
super();
this._listView = listView;
return global.__native(this);
var ListViewAdapterClass;
function ensureListViewAdapterClass() {
if (ListViewAdapterClass) {
return;
}
public getCount() {
return this._listView && this._listView.items ? this._listView.items.length : 0;
}
class ListViewAdapter extends android.widget.BaseAdapter {
private _listView: ListView;
public getItem(i: number) {
if (this._listView && this._listView.items && i < this._listView.items.length) {
return this._listView.items.getItem ? this._listView.items.getItem(i) : this._listView.items[i];
constructor(listView: ListView) {
super();
this._listView = listView;
return global.__native(this);
}
return null;
}
public getCount() {
return this._listView && this._listView.items ? this._listView.items.length : 0;
}
public getItemId(i: number) {
return long(i);
}
public getItem(i: number) {
if (this._listView && this._listView.items && i < this._listView.items.length) {
return this._listView.items.getItem ? this._listView.items.getItem(i) : this._listView.items[i];
}
public hasStableIds(): boolean {
return true;
}
public getView(index: number, convertView: android.view.View, parent: android.view.ViewGroup): android.view.View {
if (!this._listView) {
return null;
}
var view = this._listView._getRealizedView(convertView, index);
var args = <definition.ItemEventData>{
eventName: ITEMLOADING, object: this._listView, index: index, view: view,
android: parent,
ios: undefined
};
this._listView.notify(args);
if (!args.view) {
args.view = this._listView._getDefaultItemContent(index);
public getItemId(i: number) {
return long(i);
}
if (args.view) {
if (this._listView.rowHeight > -1) {
args.view.height = this._listView.rowHeight;
}
else {
args.view.height = Number.NaN;
}
this._listView._prepareItem(args.view, index);
if (!args.view.parent) {
var layoutBase: typeof layoutBaseModule = require("ui/layouts/layout-base");
public hasStableIds(): boolean {
return true;
}
if (args.view instanceof layoutBase.LayoutBase) {
this._listView._addView(args.view);
convertView = args.view.android;
} else {
var sp = new stackLayout.StackLayout();
sp.addChild(args.view);
this._listView._addView(sp);
public getView(index: number, convertView: android.view.View, parent: android.view.ViewGroup): android.view.View {
if (!this._listView) {
return null;
}
convertView = sp.android;
var view = this._listView._getRealizedView(convertView, index);
var args = <definition.ItemEventData>{
eventName: ITEMLOADING, object: this._listView, index: index, view: view,
android: parent,
ios: undefined
};
this._listView.notify(args);
if (!args.view) {
args.view = this._listView._getDefaultItemContent(index);
}
if (args.view) {
if (this._listView.rowHeight > -1) {
args.view.height = this._listView.rowHeight;
}
else {
args.view.height = Number.NaN;
}
this._listView._prepareItem(args.view, index);
if (!args.view.parent) {
var layoutBase: typeof layoutBaseModule = require("ui/layouts/layout-base");
if (args.view instanceof layoutBase.LayoutBase) {
this._listView._addView(args.view);
convertView = args.view.android;
} else {
var sp = new stackLayout.StackLayout();
sp.addChild(args.view);
this._listView._addView(sp);
convertView = sp.android;
}
}
this._listView._realizedItems[convertView.hashCode()] = args.view;
// cache the realized index (used to raise the ItemLoading event upon scroll stop)
args.view[REALIZED_INDEX] = index;
}
this._listView._realizedItems[convertView.hashCode()] = args.view;
// cache the realized index (used to raise the ItemLoading event upon scroll stop)
args.view[REALIZED_INDEX] = index;
return convertView;
}
return convertView;
}
}
ListViewAdapterClass = ListViewAdapter;
}

View File

@ -9,48 +9,57 @@ import * as colorModule from "color";
global.moduleMerge(pageCommon, exports);
class DialogFragmentClass extends android.app.DialogFragment {
private _owner: Page;
private _fullscreen: boolean;
private _dismissCallback: Function;
constructor(owner: Page, fullscreen?: boolean, dismissCallback?: Function) {
super();
this._owner = owner;
this._fullscreen = fullscreen;
this._dismissCallback = dismissCallback;
return global.__native(this);
var DialogFragmentClass;
function ensureDialogFragmentClass() {
if (DialogFragmentClass) {
return;
}
public onCreateDialog(savedInstanceState: android.os.Bundle): android.app.Dialog {
var dialog = new android.app.Dialog(this._owner._context);
dialog.requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
class DialogFragmentClassInner extends android.app.DialogFragment {
private _owner: Page;
private _fullscreen: boolean;
private _dismissCallback: Function;
// Hide actionBar and adjust alignment based on _fullscreen value.
this._owner.horizontalAlignment = this._fullscreen ? enums.HorizontalAlignment.stretch : enums.HorizontalAlignment.center;
this._owner.verticalAlignment = this._fullscreen ? enums.VerticalAlignment.stretch : enums.VerticalAlignment.center;
this._owner.actionBarHidden = true;
constructor(owner: Page, fullscreen?: boolean, dismissCallback?: Function) {
super();
dialog.setContentView(this._owner._nativeView, this._owner._nativeView.getLayoutParams());
var window = dialog.getWindow();
window.setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(android.graphics.Color.TRANSPARENT));
if (this._fullscreen) {
window.setLayout(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.FILL_PARENT);
this._owner = owner;
this._fullscreen = fullscreen;
this._dismissCallback = dismissCallback;
return global.__native(this);
}
return dialog;
}
public onDismiss() {
if (typeof this._dismissCallback === "function") {
this._dismissCallback();
public onCreateDialog(savedInstanceState: android.os.Bundle): android.app.Dialog {
var dialog = new android.app.Dialog(this._owner._context);
dialog.requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
// Hide actionBar and adjust alignment based on _fullscreen value.
this._owner.horizontalAlignment = this._fullscreen ? enums.HorizontalAlignment.stretch : enums.HorizontalAlignment.center;
this._owner.verticalAlignment = this._fullscreen ? enums.VerticalAlignment.stretch : enums.VerticalAlignment.center;
this._owner.actionBarHidden = true;
dialog.setContentView(this._owner._nativeView, this._owner._nativeView.getLayoutParams());
var window = dialog.getWindow();
window.setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(android.graphics.Color.TRANSPARENT));
if (this._fullscreen) {
window.setLayout(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.FILL_PARENT);
}
return dialog;
}
}
};
public onDismiss() {
if (typeof this._dismissCallback === "function") {
this._dismissCallback();
}
}
};
DialogFragmentClass = DialogFragmentClassInner;
}
export class Page extends pageCommon.Page {
private _isBackNavigation = false;
@ -114,7 +123,7 @@ export class Page extends pageCommon.Page {
}
/* tslint:disable */
private _dialogFragment: DialogFragmentClass;
private _dialogFragment;
/* tslint:enable */
protected _showNativeModalView(parent: Page, context: any, closeCallback: Function, fullscreen?: boolean) {
super._showNativeModalView(parent, context, closeCallback, fullscreen);
@ -128,6 +137,7 @@ export class Page extends pageCommon.Page {
this._isAddedToNativeVisualTree = true;
this.onLoaded();
ensureDialogFragmentClass();
var that = this;
this._dialogFragment = new DialogFragmentClass(this, fullscreen, function () {
that.closeModal();

View File

@ -31,7 +31,7 @@ export class ScrollView extends contentView.ContentView implements definition.Sc
public addEventListener(arg: string, callback: any, thisArg?: any) {
super.addEventListener(arg, callback, thisArg);
if (arg === definition.ScrollView.scrollEvent) {
if (arg === ScrollView.scrollEvent) {
this._scrollChangeCount++;
this.attach();
}
@ -40,7 +40,7 @@ export class ScrollView extends contentView.ContentView implements definition.Sc
public removeEventListener(arg: string, callback: any, thisArg?: any) {
super.addEventListener(arg, callback, thisArg);
if (arg === definition.ScrollView.scrollEvent) {
if (arg === ScrollView.scrollEvent) {
this._scrollChangeCount--;
this.dettach();
}

View File

@ -115,7 +115,7 @@ export class ScrollView extends common.ScrollView implements definition.ScrollVi
if (rootScrollView && rootScrollView.android) {
rootScrollView.notify(<definition.ScrollEventData>{
object: rootScrollView,
eventName: definition.ScrollView.scrollEvent,
eventName: ScrollView.scrollEvent,
scrollX: rootScrollView.android.getScrollX() / utils.layout.getDisplayDensity(),
scrollY: rootScrollView.android.getScrollY() / utils.layout.getDisplayDensity()
});

View File

@ -80,6 +80,7 @@ function onItemsPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var tabIndex: number;
if (view.selectedBackgroundColor) {
ensureSegmentedBarColorDrawableClass();
for (tabIndex = 0; tabIndex < tabHost.getTabWidget().getTabCount(); tabIndex++) {
var vg = <android.view.ViewGroup>tabHost.getTabWidget().getChildTabViewAt(tabIndex);
@ -87,7 +88,7 @@ function onItemsPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var arr = java.lang.reflect.Array.newInstance(java.lang.Integer.class.getField("TYPE").get(null), 1);
arr[0] = R_ATTR_STATE_SELECTED;
var colorDrawable = new SegmentedBarColorDrawable(view.selectedBackgroundColor.android)
var colorDrawable = new SegmentedBarColorDrawableClass(view.selectedBackgroundColor.android)
stateDrawable.addState(arr, colorDrawable);
stateDrawable.setBounds(0, 15, vg.getRight(), vg.getBottom());
@ -107,18 +108,25 @@ function onItemsPropertyChanged(data: dependencyObservable.PropertyChangeData) {
}
(<proxy.PropertyMetadata>common.SegmentedBar.itemsProperty.metadata).onSetNativeValue = onItemsPropertyChanged;
class SegmentedBarColorDrawable extends android.graphics.drawable.ColorDrawable {
constructor(arg: any) {
super(arg);
return global.__native(this);
var SegmentedBarColorDrawableClass;
function ensureSegmentedBarColorDrawableClass() {
if (SegmentedBarColorDrawableClass) {
return;
}
public draw(canvas: android.graphics.Canvas): void {
var p = new android.graphics.Paint();
p.setColor(this.getColor());
p.setStyle(android.graphics.Paint.Style.FILL);
canvas.drawRect(0, this.getBounds().height() - 15, this.getBounds().width(), this.getBounds().height(), p);
class SegmentedBarColorDrawable extends android.graphics.drawable.ColorDrawable {
constructor(arg: any) {
super(arg);
return global.__native(this);
}
public draw(canvas: android.graphics.Canvas): void {
var p = new android.graphics.Paint();
p.setColor(this.getColor());
p.setStyle(android.graphics.Paint.Style.FILL);
canvas.drawRect(0, this.getBounds().height() - 15, this.getBounds().width(), this.getBounds().height(), p);
}
}
}
@ -136,11 +144,12 @@ export class SegmentedBarItem extends common.SegmentedBarItem {
}
export class SegmentedBar extends common.SegmentedBar {
private _android: OurTabHost;
private _android;
public _listener: android.widget.TabHost.OnTabChangeListener;
public _createUI() {
this._android = new OurTabHost(this._context, null);
ensureTabHostClass();
this._android = new TabHostClass(this._context, null);
if (types.isNumber(this.selectedIndex) && this._android.getCurrentTab() !== this.selectedIndex) {
this._android.setCurrentTab(this.selectedIndex);
}
@ -177,16 +186,25 @@ export class SegmentedBar extends common.SegmentedBar {
}
}
class OurTabHost extends android.widget.TabHost {
constructor(context: any, attrs: any) {
super(context, attrs);
return global.__native(this);
var TabHostClass;
function ensureTabHostClass() {
if (TabHostClass) {
return;
}
protected onAttachedToWindow(): void {
// overriden to remove the code that will steal the focus from edit fields.
class OurTabHost extends android.widget.TabHost {
constructor(context: any, attrs: any) {
super(context, attrs);
return global.__native(this);
}
protected onAttachedToWindow(): void {
// overriden to remove the code that will steal the focus from edit fields.
}
}
TabHostClass = OurTabHost;
}
export class SegmentedBarStyler implements style.Styler {

View File

@ -1,7 +1,7 @@
import imageSource = require("image-source");
import colorModule = require("color");
import enums = require("ui/enums");
import dts = require("ui/styling/background");
import definition = require("ui/styling/background");
import cssValue = require("css-value");
import * as typesModule from "utils/types";
@ -12,7 +12,7 @@ interface CSSValue {
value?: number;
}
export class Background implements dts.Background {
export class Background implements definition.Background {
public static default = new Background(undefined, undefined, undefined, undefined, undefined);
color: colorModule.Color;
@ -55,12 +55,12 @@ export class Background implements dts.Background {
return new Background(this.color, this.image, this.repeat, this.position, value);
}
public getDrawParams(width: number, height: number): dts.BackgroundDrawParams {
public getDrawParams(width: number, height: number): definition.BackgroundDrawParams {
if (!this.image) {
return null;
}
var res: dts.BackgroundDrawParams = {
var res: definition.BackgroundDrawParams = {
repeatX: true,
repeatY: true,
posX: 0,

View File

@ -1,6 +1,6 @@
import utils = require("utils/utils");
import common = require("./background-common");
import dts = require("ui/styling/background");
import definition = require("ui/styling/background");
import view = require("ui/core/view");
import types = require("utils/types");
import * as styleModule from "./style";
@ -12,130 +12,154 @@ global.moduleMerge(common, exports);
// We are using "ad" here to avoid namespace collision with the global android object
export module ad {
export class BorderDrawable extends android.graphics.drawable.ColorDrawable implements dts.ad.BorderDrawable {
private _density = utils.layout.getDisplayDensity();
private _borderWidth: number;
private _cornerRadius: number;
private _borderColor: number;
Object.defineProperty(ad, "BorderDrawable", {
get: function () {
ensureBorderDrawable();
return BorderDrawableClass;
},
configurable: true
});
constructor() {
super();
return global.__native(this);
var BorderDrawableClass;
function ensureBorderDrawable() {
if (BorderDrawableClass) {
return;
}
get borderWidth(): number {
return this._borderWidth;
}
set borderWidth(value: number) {
if (this._borderWidth !== value) {
this._borderWidth = value;
this.invalidateSelf();
class BorderDrawable extends android.graphics.drawable.ColorDrawable implements definition.ad.BorderDrawable {
private _density = utils.layout.getDisplayDensity();
private _borderWidth: number;
private _cornerRadius: number;
private _borderColor: number;
constructor() {
super();
return global.__native(this);
}
}
get cornerRadius(): number {
return this._cornerRadius;
}
set cornerRadius(value: number) {
if (this._cornerRadius !== value) {
this._cornerRadius = value;
this.invalidateSelf();
get borderWidth(): number {
return this._borderWidth;
}
}
get borderColor(): number {
return this._borderColor;
}
set borderColor(value: number) {
if (this._borderColor !== value) {
this._borderColor = value;
this.invalidateSelf();
set borderWidth(value: number) {
if (this._borderWidth !== value) {
this._borderWidth = value;
this.invalidateSelf();
}
}
}
private _background: common.Background
get background(): common.Background {
return this._background;
}
set background(value: common.Background) {
if (this._background !== value) {
this._background = value;
this.invalidateSelf();
get cornerRadius(): number {
return this._cornerRadius;
}
set cornerRadius(value: number) {
if (this._cornerRadius !== value) {
this._cornerRadius = value;
this.invalidateSelf();
}
}
}
public draw(canvas: android.graphics.Canvas): void {
var bounds = this.getBounds();
var boundsF = new android.graphics.RectF(bounds);
var boundsWidth = bounds.width();
var boundsHeight = bounds.height();
get borderColor(): number {
return this._borderColor;
}
set borderColor(value: number) {
if (this._borderColor !== value) {
this._borderColor = value;
this.invalidateSelf();
}
}
var radius = this._cornerRadius * this._density;
var stroke = this._borderWidth * this._density;
private _background: common.Background
get background(): common.Background {
return this._background;
}
set background(value: common.Background) {
if (this._background !== value) {
this._background = value;
this.invalidateSelf();
}
}
public draw(canvas: android.graphics.Canvas): void {
var bounds = this.getBounds();
var boundsF = new android.graphics.RectF(bounds);
var boundsWidth = bounds.width();
var boundsHeight = bounds.height();
var radius = this._cornerRadius * this._density;
var stroke = this._borderWidth * this._density;
// set clip first
if (radius > 0) {
var path = new android.graphics.Path();
path.addRoundRect(boundsF, radius, radius, android.graphics.Path.Direction.CW);
canvas.clipPath(path);
}
// draw background
if (this.background.color && this.background.color.android) {
let c = this.background.color;
canvas.drawARGB(c.a, c.r, c.g, c.b);
}
// draw image
if (this.background.image) {
let bitmap = this.background.image.android;
let params = this.background.getDrawParams(boundsWidth, boundsHeight);
var matrix = new android.graphics.Matrix();
if (params.sizeX > 0 && params.sizeY > 0) {
var scaleX = params.sizeX / bitmap.getWidth();
var scaleY = params.sizeY / bitmap.getHeight();
matrix.setScale(scaleX, scaleY, 0, 0);
// set clip first
if (radius > 0) {
var path = new android.graphics.Path();
path.addRoundRect(boundsF, radius, radius, android.graphics.Path.Direction.CW);
canvas.clipPath(path);
}
else {
params.sizeX = bitmap.getWidth();
params.sizeY = bitmap.getHeight();
// draw background
if (this.background.color && this.background.color.android) {
let c = this.background.color;
canvas.drawARGB(c.a, c.r, c.g, c.b);
}
matrix.postTranslate(params.posX, params.posY);
if (!params.repeatX && !params.repeatY) {
canvas.drawBitmap(bitmap, matrix, undefined);
// draw image
if (this.background.image) {
let bitmap = this.background.image.android;
let params = this.background.getDrawParams(boundsWidth, boundsHeight);
var matrix = new android.graphics.Matrix();
if (params.sizeX > 0 && params.sizeY > 0) {
var scaleX = params.sizeX / bitmap.getWidth();
var scaleY = params.sizeY / bitmap.getHeight();
matrix.setScale(scaleX, scaleY, 0, 0);
}
else {
params.sizeX = bitmap.getWidth();
params.sizeY = bitmap.getHeight();
}
matrix.postTranslate(params.posX, params.posY);
if (!params.repeatX && !params.repeatY) {
canvas.drawBitmap(bitmap, matrix, undefined);
}
else {
var shader = new android.graphics.BitmapShader(bitmap, android.graphics.Shader.TileMode.REPEAT, android.graphics.Shader.TileMode.REPEAT);
shader.setLocalMatrix(matrix);
var paint = new android.graphics.Paint();
paint.setShader(shader);
var w = params.repeatX ? bounds.width() : params.sizeX;
var h = params.repeatY ? bounds.height() : params.sizeY;
params.posX = params.repeatX ? 0 : params.posX;
params.posY = params.repeatY ? 0 : params.posY;
canvas.drawRect(params.posX, params.posY, params.posX + w, params.posY + h, paint);
}
}
else {
var shader = new android.graphics.BitmapShader(bitmap, android.graphics.Shader.TileMode.REPEAT, android.graphics.Shader.TileMode.REPEAT);
shader.setLocalMatrix(matrix);
var paint = new android.graphics.Paint();
paint.setShader(shader);
var w = params.repeatX ? bounds.width() : params.sizeX;
var h = params.repeatY ? bounds.height() : params.sizeY;
// draw border (topmost)
if (stroke > 0 && this._borderColor && this._borderColor) {
let borderPaint = new android.graphics.Paint();
borderPaint.setStyle(android.graphics.Paint.Style.STROKE);
borderPaint.setColor(this._borderColor);
params.posX = params.repeatX ? 0 : params.posX;
params.posY = params.repeatY ? 0 : params.posY;
canvas.drawRect(params.posX, params.posY, params.posX + w, params.posY + h, paint);
// Note: Double the stroke as the outer part will be clipped.
borderPaint.setStrokeWidth(stroke * 2);
canvas.drawRoundRect(boundsF, radius, radius, borderPaint)
}
}
// draw border (topmost)
if (stroke > 0 && this._borderColor && this._borderColor) {
let borderPaint = new android.graphics.Paint();
borderPaint.setStyle(android.graphics.Paint.Style.STROKE);
borderPaint.setColor(this._borderColor);
// Note: Double the stroke as the outer part will be clipped.
borderPaint.setStrokeWidth(stroke * 2);
canvas.drawRoundRect(boundsF, radius, radius, borderPaint)
}
}
BorderDrawableClass = BorderDrawable;
}
var SDK = android.os.Build.VERSION.SDK_INT;
var SDK: number;
function getSDK() {
if (!SDK) {
SDK = android.os.Build.VERSION.SDK_INT;
}
return SDK;
}
var _defaultBackgrounds = new Map<string, android.graphics.drawable.Drawable>();
@ -164,8 +188,8 @@ export module ad {
bkg.backgroundColor = backgroundColor;
} else if (v.borderWidth !== 0 || v.borderRadius !== 0 || !backgroundValue.isEmpty()) {
if (!(bkg instanceof dts.ad.BorderDrawable)) {
bkg = new dts.ad.BorderDrawable();
if (!(bkg instanceof BorderDrawableClass)) {
bkg = new BorderDrawableClass();
let viewClass = types.getClass(v);
if (!(v instanceof btn.Button) && !_defaultBackgrounds.has(viewClass)) {
_defaultBackgrounds.set(viewClass, nativeView.getBackground());
@ -179,7 +203,7 @@ export module ad {
bkg.borderColor = v.borderColor ? v.borderColor.android : android.graphics.Color.TRANSPARENT;
bkg.background = backgroundValue;
if (SDK < 18) {
if (getSDK() < 18) {
// Switch to software because of unsupported canvas methods if hardware acceleration is on:
// http://developer.android.com/guide/topics/graphics/hardware-accel.html
nativeView.setLayerType(android.view.View.LAYER_TYPE_SOFTWARE, null);
@ -201,7 +225,7 @@ export module ad {
}
}
if (SDK < 18) {
if (getSDK() < 18) {
// Reset layer type to hardware
nativeView.setLayerType(android.view.View.LAYER_TYPE_HARDWARE, null);
}

View File

@ -29,120 +29,138 @@ export class TabViewItem extends common.TabViewItem {
}
}
class PagerAdapterClass extends android.support.v4.view.PagerAdapter {
private owner: TabView;
private items: Array<definition.TabViewItem>;
constructor(owner: TabView, items: Array<definition.TabViewItem>) {
super();
this.owner = owner;
this.items = items;
return global.__native(this);
var PagerAdapterClass;
function ensurePagerAdapterClass() {
if (PagerAdapterClass) {
return;
}
getCount() {
return this.items ? this.items.length : 0;
}
class PagerAdapterClassInner extends android.support.v4.view.PagerAdapter {
private owner: TabView;
private items: Array<definition.TabViewItem>;
getPageTitle(index: number) {
if (index < 0 || index >= this.items.length) {
return "";
constructor(owner: TabView, items: Array<definition.TabViewItem>) {
super();
this.owner = owner;
this.items = items;
return global.__native(this);
}
return this.items[index].title;
}
instantiateItem(container: android.view.ViewGroup, index: number) {
trace.write("TabView.PagerAdapter.instantiateItem; container: " + container + "; index: " + index, common.traceCategory);
var item = this.items[index];
if (item.view.parent !== this.owner) {
this.owner._addView(item.view);
getCount() {
return this.items ? this.items.length : 0;
}
if (this[VIEWS_STATES]) {
trace.write("TabView.PagerAdapter.instantiateItem; restoreHierarchyState: " + item.view, common.traceCategory);
item.view.android.restoreHierarchyState(this[VIEWS_STATES]);
}
container.addView(item.view.android);
return item.view.android;
}
destroyItem(container: android.view.ViewGroup, index: number, _object: any) {
trace.write("TabView.PagerAdapter.destroyItem; container: " + container + "; index: " + index + "; _object: " + _object, common.traceCategory);
var item = this.items[index];
var nativeView = item.view.android;
if (nativeView.toString() !== _object.toString()) {
throw new Error("Expected " + nativeView.toString() + " to equal " + _object.toString());
}
if (!this[VIEWS_STATES]) {
this[VIEWS_STATES] = new android.util.SparseArray<android.os.Parcelable>();
}
nativeView.saveHierarchyState(this[VIEWS_STATES]);
container.removeView(nativeView);
// Note: this.owner._removeView will clear item.view.android.
// So call this after the native instance is removed form the container.
if (item.view.parent === this.owner) {
this.owner._removeView(item.view);
}
}
isViewFromObject(view: android.view.View, _object: any) {
return view === _object;
}
saveState(): android.os.Parcelable {
trace.write("TabView.PagerAdapter.saveState", common.traceCategory);
var owner: TabView = this.owner;
if (!owner || owner._childrenCount === 0) {
return null;
}
if (!this[VIEWS_STATES]) {
this[VIEWS_STATES] = new android.util.SparseArray<android.os.Parcelable>();
}
var viewStates = this[VIEWS_STATES];
var childCallback = function (view: view.View): boolean {
var nativeView: android.view.View = view.android;
if (nativeView && nativeView.isSaveFromParentEnabled && nativeView.isSaveFromParentEnabled()) {
nativeView.saveHierarchyState(viewStates);
getPageTitle(index: number) {
if (index < 0 || index >= this.items.length) {
return "";
}
return true;
return this.items[index].title;
}
owner._eachChildView(childCallback);
var bundle = new android.os.Bundle();
bundle.putSparseParcelableArray(VIEWS_STATES, viewStates);
return bundle;
instantiateItem(container: android.view.ViewGroup, index: number) {
trace.write("TabView.PagerAdapter.instantiateItem; container: " + container + "; index: " + index, common.traceCategory);
var item = this.items[index];
if (item.view.parent !== this.owner) {
this.owner._addView(item.view);
}
if (this[VIEWS_STATES]) {
trace.write("TabView.PagerAdapter.instantiateItem; restoreHierarchyState: " + item.view, common.traceCategory);
item.view.android.restoreHierarchyState(this[VIEWS_STATES]);
}
container.addView(item.view.android);
return item.view.android;
}
destroyItem(container: android.view.ViewGroup, index: number, _object: any) {
trace.write("TabView.PagerAdapter.destroyItem; container: " + container + "; index: " + index + "; _object: " + _object, common.traceCategory);
var item = this.items[index];
var nativeView = item.view.android;
if (nativeView.toString() !== _object.toString()) {
throw new Error("Expected " + nativeView.toString() + " to equal " + _object.toString());
}
if (!this[VIEWS_STATES]) {
this[VIEWS_STATES] = new android.util.SparseArray<android.os.Parcelable>();
}
nativeView.saveHierarchyState(this[VIEWS_STATES]);
container.removeView(nativeView);
// Note: this.owner._removeView will clear item.view.android.
// So call this after the native instance is removed form the container.
if (item.view.parent === this.owner) {
this.owner._removeView(item.view);
}
}
isViewFromObject(view: android.view.View, _object: any) {
return view === _object;
}
saveState(): android.os.Parcelable {
trace.write("TabView.PagerAdapter.saveState", common.traceCategory);
var owner: TabView = this.owner;
if (!owner || owner._childrenCount === 0) {
return null;
}
if (!this[VIEWS_STATES]) {
this[VIEWS_STATES] = new android.util.SparseArray<android.os.Parcelable>();
}
var viewStates = this[VIEWS_STATES];
var childCallback = function (view: view.View): boolean {
var nativeView: android.view.View = view.android;
if (nativeView && nativeView.isSaveFromParentEnabled && nativeView.isSaveFromParentEnabled()) {
nativeView.saveHierarchyState(viewStates);
}
return true;
}
owner._eachChildView(childCallback);
var bundle = new android.os.Bundle();
bundle.putSparseParcelableArray(VIEWS_STATES, viewStates);
return bundle;
}
restoreState(state: android.os.Parcelable, loader: java.lang.ClassLoader) {
trace.write("TabView.PagerAdapter.restoreState", common.traceCategory);
var bundle: android.os.Bundle = <android.os.Bundle>state;
bundle.setClassLoader(loader);
this[VIEWS_STATES] = bundle.getSparseParcelableArray(VIEWS_STATES);
}
};
PagerAdapterClass = PagerAdapterClassInner;
}
var PageChangedListenerClass;
function ensurePageChangedListenerClass() {
if (PageChangedListenerClass) {
return;
}
restoreState(state: android.os.Parcelable, loader: java.lang.ClassLoader) {
trace.write("TabView.PagerAdapter.restoreState", common.traceCategory);
var bundle: android.os.Bundle = <android.os.Bundle>state;
bundle.setClassLoader(loader);
this[VIEWS_STATES] = bundle.getSparseParcelableArray(VIEWS_STATES);
}
};
class PageChangedListener extends android.support.v4.view.ViewPager.SimpleOnPageChangeListener {
private _owner: TabView;
constructor(owner: TabView) {
super();
this._owner = owner;
return global.__native(this);
}
class PageChangedListener extends android.support.v4.view.ViewPager.SimpleOnPageChangeListener {
private _owner: TabView;
constructor(owner: TabView) {
super();
this._owner = owner;
return global.__native(this);
public onPageSelected(position: number) {
this._owner.selectedIndex = position;
}
}
public onPageSelected(position: number) {
this._owner.selectedIndex = position;
}
PageChangedListenerClass = PageChangedListener;
}
function selectedColorPropertyChanged(data: dependencyObservable.PropertyChangeData) {
@ -168,7 +186,7 @@ export class TabView extends common.TabView {
private _pagerAdapter: android.support.v4.view.PagerAdapter;
private _androidViewId: number;
private _pageChagedListener: PageChangedListener;
private _pageChagedListener;
get android(): android.view.View {
return this._grid;
@ -207,7 +225,8 @@ export class TabView extends common.TabView {
}
this._grid.setId(this._androidViewId);
this._pageChagedListener = new PageChangedListener(this);
ensurePageChangedListenerClass();
this._pageChagedListener = new PageChangedListenerClass(this);
(<any>this._viewPager).addOnPageChangeListener(this._pageChagedListener);
}
@ -248,6 +267,7 @@ export class TabView extends common.TabView {
tabItems.push(this.createTabItem(item));
});
ensurePagerAdapterClass();
this._pagerAdapter = new PagerAdapterClass(this, data.newValue);
this._viewPager.setAdapter(this._pagerAdapter);

View File

@ -4,68 +4,77 @@ import * as fileSystemModule from "file-system";
global.moduleMerge(common, exports);
export class WebViewClientClass extends android.webkit.WebViewClient {
private _view: common.WebView;
constructor(view: common.WebView) {
super();
this._view = view;
return global.__native(this);
var WebViewClientClass;
function ensureWebViewClientClass() {
if (WebViewClientClass) {
return;
}
public shouldOverrideUrlLoading(view: android.webkit.WebView, url: string) {
trace.write("WebViewClientClass.shouldOverrideUrlLoading(" + url + ")", trace.categories.Debug);
return false;
}
class WebViewClientClassInner extends android.webkit.WebViewClient {
private _view: common.WebView;
public onPageStarted(view: android.webkit.WebView, url: string, favicon: android.graphics.Bitmap) {
super.onPageStarted(view, url, favicon);
constructor(view: common.WebView) {
super();
if (this._view) {
trace.write("WebViewClientClass.onPageStarted(" + url + ", " + favicon + ")", trace.categories.Debug);
this._view._onLoadStarted(url);
this._view = view;
return global.__native(this);
}
}
public onPageFinished(view: android.webkit.WebView, url: string) {
super.onPageFinished(view, url);
if (this._view) {
trace.write("WebViewClientClass.onPageFinished(" + url + ")", trace.categories.Debug);
this._view._onLoadFinished(url, undefined);
public shouldOverrideUrlLoading(view: android.webkit.WebView, url: string) {
trace.write("WebViewClientClass.shouldOverrideUrlLoading(" + url + ")", trace.categories.Debug);
return false;
}
}
public onReceivedError() {
var view: android.webkit.WebView = arguments[0];
if (arguments.length === 4) {
var errorCode: number = arguments[1];
var description: string = arguments[2];
var failingUrl: string = arguments[3];
super.onReceivedError(view, errorCode, description, failingUrl);
public onPageStarted(view: android.webkit.WebView, url: string, favicon: android.graphics.Bitmap) {
super.onPageStarted(view, url, favicon);
if (this._view) {
trace.write("WebViewClientClass.onReceivedError(" + errorCode + ", " + description + ", " + failingUrl + ")", trace.categories.Debug);
this._view._onLoadFinished(failingUrl, description + "(" + errorCode + ")");
trace.write("WebViewClientClass.onPageStarted(" + url + ", " + favicon + ")", trace.categories.Debug);
this._view._onLoadStarted(url);
}
} else {
}
var request: any = arguments[1];
var error: any = arguments[2];
super.onReceivedError(view, request, error);
public onPageFinished(view: android.webkit.WebView, url: string) {
super.onPageFinished(view, url);
if (this._view) {
trace.write("WebViewClientClass.onReceivedError(" + error.getErrorCode() + ", " + error.getDescription() + ", " + (error.getUrl && error.getUrl()) + ")", trace.categories.Debug);
this._view._onLoadFinished(error.getUrl && error.getUrl(), error.getDescription() + "(" + error.getErrorCode() + ")");
trace.write("WebViewClientClass.onPageFinished(" + url + ")", trace.categories.Debug);
this._view._onLoadFinished(url, undefined);
}
}
}
};
}
public onReceivedError() {
var view: android.webkit.WebView = arguments[0];
if (arguments.length === 4) {
var errorCode: number = arguments[1];
var description: string = arguments[2];
var failingUrl: string = arguments[3];
super.onReceivedError(view, errorCode, description, failingUrl);
if (this._view) {
trace.write("WebViewClientClass.onReceivedError(" + errorCode + ", " + description + ", " + failingUrl + ")", trace.categories.Debug);
this._view._onLoadFinished(failingUrl, description + "(" + errorCode + ")");
}
} else {
var request: any = arguments[1];
var error: any = arguments[2];
super.onReceivedError(view, request, error);
if (this._view) {
trace.write("WebViewClientClass.onReceivedError(" + error.getErrorCode() + ", " + error.getDescription() + ", " + (error.getUrl && error.getUrl()) + ")", trace.categories.Debug);
this._view._onLoadFinished(error.getUrl && error.getUrl(), error.getDescription() + "(" + error.getErrorCode() + ")");
}
}
}
};
WebViewClientClass = WebViewClientClassInner;
}
export class WebView extends common.WebView {
private _android: android.webkit.WebView;
@ -74,6 +83,7 @@ export class WebView extends common.WebView {
constructor() {
super();
ensureWebViewClientClass();
this._webViewClient = new WebViewClientClass(this);
}

View File

@ -3,8 +3,13 @@ import { knownFolders } from "file-system"
export var debug = true;
// TODO: Get this from the runtimes...
var applicationRootPath = knownFolders.currentApp().path;
applicationRootPath = applicationRootPath.substr(0, applicationRootPath.length - "app/".length);
var applicationRootPath;
function ensureAppRootPath() {
if (!applicationRootPath) {
applicationRootPath = knownFolders.currentApp().path;
applicationRootPath = applicationRootPath.substr(0, applicationRootPath.length - "app/".length);
}
}
export class Source {
private _uri: string;
@ -14,7 +19,9 @@ export class Source {
private static _source: symbol = Symbol("source");
private static _appRoot: string;
constructor(uri: string, line: number, column: number) {
constructor(uri: string, line: number, column: number) {
ensureAppRootPath();
if (uri.length > applicationRootPath.length && uri.substr(0, applicationRootPath.length) === applicationRootPath) {
this._uri = "file://" + uri.substr(applicationRootPath.length);
} else {