mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-17 12:57:42 +08:00
Initial prototype of Frame + Page + Navigation.
This commit is contained in:
36
BCL.csproj
36
BCL.csproj
@ -153,14 +153,18 @@
|
|||||||
<DependentUpon>text.d.ts</DependentUpon>
|
<DependentUpon>text.d.ts</DependentUpon>
|
||||||
</TypeScriptCompile>
|
</TypeScriptCompile>
|
||||||
<TypeScriptCompile Include="ui\core\bindable.ts" />
|
<TypeScriptCompile Include="ui\core\bindable.ts" />
|
||||||
<TypeScriptCompile Include="ui\core\index.ts" />
|
|
||||||
<TypeScriptCompile Include="ui\core\proxy.ts" />
|
<TypeScriptCompile Include="ui\core\proxy.ts" />
|
||||||
<TypeScriptCompile Include="ui\core\view.android.ts">
|
<TypeScriptCompile Include="ui\frame\frame-common.ts">
|
||||||
<DependentUpon>view.d.ts</DependentUpon>
|
<DependentUpon>frame.d.ts</DependentUpon>
|
||||||
</TypeScriptCompile>
|
</TypeScriptCompile>
|
||||||
<TypeScriptCompile Include="ui\core\view.ios.ts">
|
<TypeScriptCompile Include="ui\frame\frame.android.ts">
|
||||||
<DependentUpon>view.d.ts</DependentUpon>
|
<DependentUpon>frame.d.ts</DependentUpon>
|
||||||
</TypeScriptCompile>
|
</TypeScriptCompile>
|
||||||
|
<TypeScriptCompile Include="ui\frame\frame.d.ts" />
|
||||||
|
<TypeScriptCompile Include="ui\frame\frame.ios.ts">
|
||||||
|
<DependentUpon>frame.d.ts</DependentUpon>
|
||||||
|
</TypeScriptCompile>
|
||||||
|
<TypeScriptCompile Include="ui\frame\index.ts" />
|
||||||
<TypeScriptCompile Include="ui\image\image.android.ts">
|
<TypeScriptCompile Include="ui\image\image.android.ts">
|
||||||
<DependentUpon>image.d.ts</DependentUpon>
|
<DependentUpon>image.d.ts</DependentUpon>
|
||||||
</TypeScriptCompile>
|
</TypeScriptCompile>
|
||||||
@ -177,14 +181,22 @@
|
|||||||
<TypeScriptCompile Include="ui\label\label.ios.ts">
|
<TypeScriptCompile Include="ui\label\label.ios.ts">
|
||||||
<DependentUpon>label.d.ts</DependentUpon>
|
<DependentUpon>label.d.ts</DependentUpon>
|
||||||
</TypeScriptCompile>
|
</TypeScriptCompile>
|
||||||
<TypeScriptCompile Include="ui\text-input\index.ts" />
|
<TypeScriptCompile Include="ui\pages\index.ts" />
|
||||||
<TypeScriptCompile Include="ui\text-input\text-input.android.ts">
|
<TypeScriptCompile Include="ui\pages\page-common.ts">
|
||||||
<DependentUpon>text-input.d.ts</DependentUpon>
|
<DependentUpon>page.d.ts</DependentUpon>
|
||||||
</TypeScriptCompile>
|
</TypeScriptCompile>
|
||||||
<TypeScriptCompile Include="ui\text-input\text-input.ios.ts">
|
<TypeScriptCompile Include="ui\pages\page.android.ts">
|
||||||
<DependentUpon>text-input.d.ts</DependentUpon>
|
<DependentUpon>page.d.ts</DependentUpon>
|
||||||
|
</TypeScriptCompile>
|
||||||
|
<TypeScriptCompile Include="ui\pages\page.d.ts" />
|
||||||
|
<TypeScriptCompile Include="ui\text-field\index.ts" />
|
||||||
|
<TypeScriptCompile Include="ui\text-field\text-field.android.ts">
|
||||||
|
<DependentUpon>text-field.d.ts</DependentUpon>
|
||||||
|
</TypeScriptCompile>
|
||||||
|
<TypeScriptCompile Include="ui\text-field\text-field.d.ts" />
|
||||||
|
<TypeScriptCompile Include="ui\text-field\text-field.ios.ts">
|
||||||
|
<DependentUpon>text-field.d.ts</DependentUpon>
|
||||||
</TypeScriptCompile>
|
</TypeScriptCompile>
|
||||||
<TypeScriptCompile Include="ui\text-input\text-input.d.ts" />
|
|
||||||
<TypeScriptCompile Include="utils\module-merge.ts" />
|
<TypeScriptCompile Include="utils\module-merge.ts" />
|
||||||
<TypeScriptCompile Include="utils\utils_android.ts" />
|
<TypeScriptCompile Include="utils\utils_android.ts" />
|
||||||
<TypeScriptCompile Include="utils\utils_ios.ts" />
|
<TypeScriptCompile Include="utils\utils_ios.ts" />
|
||||||
@ -247,7 +259,7 @@
|
|||||||
<TypeScriptCompile Include="libjs.d.ts" />
|
<TypeScriptCompile Include="libjs.d.ts" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<TypeScriptCompile Include="ui\core\view.d.ts" />
|
<TypeScriptCompile Include="ui\core\view.ts" />
|
||||||
<TypeScriptCompile Include="ui\core\observable.ts" />
|
<TypeScriptCompile Include="ui\core\observable.ts" />
|
||||||
<TypeScriptCompile Include="ui\dialogs\dialogs.android.ts">
|
<TypeScriptCompile Include="ui\dialogs\dialogs.android.ts">
|
||||||
<DependentUpon>dialogs.d.ts</DependentUpon>
|
<DependentUpon>dialogs.d.ts</DependentUpon>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import appModule = require("application/application-common");
|
import appModule = require("application/application-common");
|
||||||
import dts = require("application");
|
import dts = require("application");
|
||||||
|
import frame = require("ui/frame");
|
||||||
|
|
||||||
// merge the exports of the application_common file with the exports of this file
|
// merge the exports of the application_common file with the exports of this file
|
||||||
declare var exports;
|
declare var exports;
|
||||||
@ -112,7 +113,7 @@ class AndroidApplication implements dts.AndroidApplication {
|
|||||||
public foregroundActivity: android.app.Activity;
|
public foregroundActivity: android.app.Activity;
|
||||||
public startActivity: android.app.Activity;
|
public startActivity: android.app.Activity;
|
||||||
public packageName: string;
|
public packageName: string;
|
||||||
public getActivity: (intent: android.content.Intent) => any;
|
// public getActivity: (intent: android.content.Intent) => any;
|
||||||
|
|
||||||
public onActivityCreated: (activity: android.app.Activity, bundle: android.os.Bundle) => void;
|
public onActivityCreated: (activity: android.app.Activity, bundle: android.os.Bundle) => void;
|
||||||
public onActivityDestroyed: (activity: android.app.Activity) => void;
|
public onActivityDestroyed: (activity: android.app.Activity) => void;
|
||||||
@ -128,7 +129,15 @@ class AndroidApplication implements dts.AndroidApplication {
|
|||||||
this.nativeApp = nativeApp;
|
this.nativeApp = nativeApp;
|
||||||
this.packageName = nativeApp.getPackageName();
|
this.packageName = nativeApp.getPackageName();
|
||||||
this.context = nativeApp.getApplicationContext();
|
this.context = nativeApp.getApplicationContext();
|
||||||
this.getActivity = undefined;
|
}
|
||||||
|
|
||||||
|
public getActivity(intent: android.content.Intent): any {
|
||||||
|
var currentPage = rootFrame.currentPage;
|
||||||
|
if (!currentPage) {
|
||||||
|
throw new Error("Root frame not navigated to a page.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentPage.android.getActivityExtends();
|
||||||
}
|
}
|
||||||
|
|
||||||
public init() {
|
public init() {
|
||||||
@ -137,3 +146,6 @@ class AndroidApplication implements dts.AndroidApplication {
|
|||||||
this.context = this.nativeApp.getApplicationContext();
|
this.context = this.nativeApp.getApplicationContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The root frame of the application
|
||||||
|
export var rootFrame = new frame.Frame();
|
10
application/application.d.ts
vendored
10
application/application.d.ts
vendored
@ -1,11 +1,13 @@
|
|||||||
|
|
||||||
declare module "application" {
|
declare module "application" {
|
||||||
|
import frame = require("ui/frame");
|
||||||
|
|
||||||
|
export var rootFrame: frame.Frame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main entry point event. This method is expected to return an instance of the root UI for the application.
|
* The main entry point event. This method is expected to use the root frame to navigate to the main application page.
|
||||||
* This will be an Activity extends for Android and a RootViewController for iOS.
|
|
||||||
*/
|
*/
|
||||||
export function onLaunch(): any;
|
export function onLaunch(): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will be called when the Application is suspended.
|
* This method will be called when the Application is suspended.
|
||||||
@ -85,7 +87,7 @@ declare module "application" {
|
|||||||
* This method is called by the JavaScript Bridge when navigation to a new activity is triggered.
|
* This method is called by the JavaScript Bridge when navigation to a new activity is triggered.
|
||||||
* The return value of this method should be com.tns.NativeScriptActivity.extends implementation.
|
* The return value of this method should be com.tns.NativeScriptActivity.extends implementation.
|
||||||
*/
|
*/
|
||||||
getActivity: (intent: android.content.Intent) => any;
|
getActivity(intent: android.content.Intent): any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Direct handler of the android.app.Application.ActivityLifecycleCallbacks.onActivityCreated method.
|
* Direct handler of the android.app.Application.ActivityLifecycleCallbacks.onActivityCreated method.
|
||||||
|
1
declarations.android.d.ts
vendored
1
declarations.android.d.ts
vendored
@ -338,6 +338,7 @@ declare module android {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
declare var app;
|
declare var app;
|
||||||
declare var telerik;
|
declare var telerik;
|
||||||
declare var gc: () => any;
|
declare var gc: () => any;
|
||||||
|
@ -37,6 +37,11 @@ export class Bindable extends observable.Observable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setPropertyCore(data: observable.PropertyChangeData) {
|
||||||
|
super.setPropertyCore(data);
|
||||||
|
this.updateTwoWayBinding(data.propertyName, data.value);
|
||||||
|
}
|
||||||
|
|
||||||
public getBinding(propertyName: string) {
|
public getBinding(propertyName: string) {
|
||||||
return this._bindings[propertyName];
|
return this._bindings[propertyName];
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -31,6 +31,13 @@ export class Observable {
|
|||||||
private _trackChanging = false;
|
private _trackChanging = false;
|
||||||
|
|
||||||
constructor(body?: any) {
|
constructor(body?: any) {
|
||||||
|
if (body) {
|
||||||
|
for (var key in body) {
|
||||||
|
// TODO: Is this correct
|
||||||
|
this[key] = body[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.on = this.addEventListener = this.addObserver;
|
this.on = this.addEventListener = this.addObserver;
|
||||||
this.off = this.removeEventListener = this.removeObserver;
|
this.off = this.removeEventListener = this.removeObserver;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import bindable = require("ui/core/bindable");
|
|||||||
export class ProxyObject extends bindable.Bindable {
|
export class ProxyObject extends bindable.Bindable {
|
||||||
public setPropertyCore(data: observable.PropertyChangeData) {
|
public setPropertyCore(data: observable.PropertyChangeData) {
|
||||||
this.setNativeProperty(data);
|
this.setNativeProperty(data);
|
||||||
|
this.updateTwoWayBinding(data.propertyName, data.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setNativeProperty(data: observable.PropertyChangeData) {
|
public setNativeProperty(data: observable.PropertyChangeData) {
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
import proxy = require("ui/core/proxy");
|
|
||||||
|
|
||||||
export class View extends proxy.ProxyObject {
|
|
||||||
public addToParent(parent: android.view.ViewGroup) {
|
|
||||||
var nativeInstance: android.view.View = this["android"];
|
|
||||||
if (nativeInstance) {
|
|
||||||
// TODO: Check for existing parent
|
|
||||||
parent.addView(nativeInstance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
7
ui/core/view.d.ts
vendored
7
ui/core/view.d.ts
vendored
@ -1,7 +0,0 @@
|
|||||||
import proxy = require("ui/core/proxy");
|
|
||||||
|
|
||||||
export declare class View extends proxy.ProxyObject {
|
|
||||||
public addToParent(parent: any);
|
|
||||||
android: any;
|
|
||||||
ios: any;
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
import proxy = require("ui/core/proxy");
|
|
||||||
|
|
||||||
export class View extends proxy.ProxyObject {
|
|
||||||
public addToParent(parent: UIKit.UIView) {
|
|
||||||
var nativeInstance: UIKit.UIView = this["ios"];
|
|
||||||
if (nativeInstance) {
|
|
||||||
// TODO: Check for existing parent
|
|
||||||
parent.addSubview(nativeInstance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
99
ui/core/view.ts
Normal file
99
ui/core/view.ts
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import proxy = require("ui/core/proxy");
|
||||||
|
import application = require("application");
|
||||||
|
|
||||||
|
export class View extends proxy.ProxyObject {
|
||||||
|
private _parent: Panel;
|
||||||
|
|
||||||
|
public onInitialized(content: android.content.Context) {
|
||||||
|
// TODO: This is used by Android, rethink this routine
|
||||||
|
}
|
||||||
|
|
||||||
|
public addToParent(native: any) {
|
||||||
|
// TODO: Temporary
|
||||||
|
if (application.ios && this.ios) {
|
||||||
|
native.addSubview(this.ios);
|
||||||
|
} else if (application.android && this.android) {
|
||||||
|
native.addView(this.android);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Panel instance that parents this view. This property is read-only.
|
||||||
|
*/
|
||||||
|
get parent(): Panel {
|
||||||
|
return this._parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the android-specific native instance that lies behind this view. Will be available if running on an Android platform.
|
||||||
|
*/
|
||||||
|
get android(): any {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ios-specific native instance that lies behind this view. Will be available if running on an Android platform.
|
||||||
|
*/
|
||||||
|
get ios(): any {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Should these be public?
|
||||||
|
public onAddedToParent(parent: Panel) {
|
||||||
|
this._parent = parent;
|
||||||
|
// TODO: Attach to parent - e.g. update data context, bindings, styling, etc.
|
||||||
|
}
|
||||||
|
|
||||||
|
public onRemovedFromParent() {
|
||||||
|
this._parent = null;
|
||||||
|
// TODO: Detach from parent.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Panel class represents an extended View which can have other views as children.
|
||||||
|
*/
|
||||||
|
export class Panel extends View {
|
||||||
|
private _children: Array<View>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._children = new Array<View>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public addChild(child: View) {
|
||||||
|
// Validate child is not parented
|
||||||
|
if (child.parent) {
|
||||||
|
var message;
|
||||||
|
if (child.parent === this) {
|
||||||
|
message = "View already added to this panel.";
|
||||||
|
} else {
|
||||||
|
message = "View is already a child of another panel.";
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._children.push(child);
|
||||||
|
child.onAddedToParent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeChild(child: View) {
|
||||||
|
if (!child) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child.parent !== this) {
|
||||||
|
throw new Error("View is not parented by this panel.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = this._children.indexOf(child);
|
||||||
|
if (index < 0) {
|
||||||
|
throw new Error("View not found in children collection.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this._children.splice(index, 1);
|
||||||
|
child.onRemovedFromParent();
|
||||||
|
}
|
||||||
|
}
|
114
ui/frame/frame-common.ts
Normal file
114
ui/frame/frame-common.ts
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
import frame = require("ui/frame");
|
||||||
|
import view = require("ui/core/view");
|
||||||
|
import pages = require("ui/pages");
|
||||||
|
|
||||||
|
enum NavigationType {
|
||||||
|
New,
|
||||||
|
Back,
|
||||||
|
Forward
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Frame extends view.View implements frame.Frame {
|
||||||
|
private _backStack: Array<frame.PageNavigationEntry>;
|
||||||
|
private _forwardStack: Array<frame.PageNavigationEntry>;
|
||||||
|
private _currentEntry: frame.PageNavigationEntry;
|
||||||
|
private _currentPage: pages.Page;
|
||||||
|
private _navigationType: NavigationType;
|
||||||
|
|
||||||
|
// TODO: Currently our navigation will not be synchronized in case users directly call native navigation methods like Activity.startActivity.
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._backStack = new Array<frame.PageNavigationEntry>();
|
||||||
|
this._forwardStack = new Array<frame.PageNavigationEntry>();
|
||||||
|
this._navigationType = NavigationType.New;
|
||||||
|
}
|
||||||
|
|
||||||
|
public canGoBack(): boolean {
|
||||||
|
return this._backStack.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public canGoForward(): boolean {
|
||||||
|
return this._forwardStack.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public goBack() {
|
||||||
|
if (!this.canGoBack()) {
|
||||||
|
// TODO: Do we need to throw an error?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entry = this._backStack.pop();
|
||||||
|
this._navigationType = NavigationType.Back;
|
||||||
|
this.navigate(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public goForward() {
|
||||||
|
if (!this.canGoForward()) {
|
||||||
|
// TODO: Do we need to throw an error?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entry = this._forwardStack.pop();
|
||||||
|
this._navigationType = NavigationType.Forward;
|
||||||
|
this.navigate(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public navigate(entry: frame.PageNavigationEntry) {
|
||||||
|
if (this._currentPage) {
|
||||||
|
this._backStack.push(this._currentEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform the actual navigation, depending on the requested navigation type
|
||||||
|
switch (this._navigationType) {
|
||||||
|
case NavigationType.New:
|
||||||
|
this.navigateCore(entry.context);
|
||||||
|
break;
|
||||||
|
case NavigationType.Back:
|
||||||
|
this.goBackCore();
|
||||||
|
if (this._currentPage) {
|
||||||
|
this._forwardStack.push(this._currentEntry);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NavigationType.Forward:
|
||||||
|
this.goForwardCore();
|
||||||
|
if (this._currentPage) {
|
||||||
|
this._backStack.push(this._currentEntry);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: We assume here that there is a Page object in the exports of the required module. This should be well documented.
|
||||||
|
this._currentPage = require(entry.pageModuleName).Page;
|
||||||
|
this._currentPage.frame = this;
|
||||||
|
this._currentEntry = entry;
|
||||||
|
|
||||||
|
// notify the page
|
||||||
|
this._currentPage.onNavigatedTo(entry.context);
|
||||||
|
|
||||||
|
// reset the navigation type back to new
|
||||||
|
this._navigationType = NavigationType.New;
|
||||||
|
}
|
||||||
|
|
||||||
|
public goBackCore() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public goForwardCore() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public navigateCore(context: any) {
|
||||||
|
}
|
||||||
|
|
||||||
|
get backStack(): Array<frame.PageNavigationEntry> {
|
||||||
|
return this._backStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
get forwardStack(): Array<frame.PageNavigationEntry> {
|
||||||
|
return this._forwardStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentPage(): pages.Page {
|
||||||
|
return this._currentPage;
|
||||||
|
}
|
||||||
|
}
|
35
ui/frame/frame.android.ts
Normal file
35
ui/frame/frame.android.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import frameCommon = require("ui/frame/frame-common");
|
||||||
|
import frame = require("ui/frame");
|
||||||
|
import pages = require("ui/pages");
|
||||||
|
import application = require("application");
|
||||||
|
|
||||||
|
export class Frame extends frameCommon.Frame {
|
||||||
|
public navigateCore(context: any) {
|
||||||
|
if (this.backStack.length === 0) {
|
||||||
|
// When navigating for the very first time we do not want to start an activity
|
||||||
|
// TODO: Revisit/polish this behavior
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var activity = this.currentPage.android.activity;
|
||||||
|
if (!activity) {
|
||||||
|
throw new Error("Current page does have an activity created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var intent = new android.content.Intent(activity, (<any>com).tns.NativeScriptActivity.class);
|
||||||
|
activity.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public goBackCore() {
|
||||||
|
var activity = this.currentPage.android.activity;
|
||||||
|
if (!activity) {
|
||||||
|
throw new Error("Current page does have an activity created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This is not true in all cases, update once added support for parent activity in Android manifest
|
||||||
|
activity.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
public goForwardCore() {
|
||||||
|
}
|
||||||
|
}
|
24
ui/frame/frame.d.ts
vendored
Normal file
24
ui/frame/frame.d.ts
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
declare module "ui/frame" {
|
||||||
|
import view = require("ui/core/view");
|
||||||
|
|
||||||
|
// There is a cyclic reference here (pages module requires frame) but it is intented and needed.
|
||||||
|
import pages = require("ui/pages");
|
||||||
|
|
||||||
|
export class Frame extends view.View {
|
||||||
|
goBack();
|
||||||
|
canGoBack(): boolean;
|
||||||
|
goForward();
|
||||||
|
canGoForward(): boolean;
|
||||||
|
navigate(entry: PageNavigationEntry);
|
||||||
|
|
||||||
|
currentPage: pages.Page;
|
||||||
|
|
||||||
|
backStack: Array<PageNavigationEntry>;
|
||||||
|
forwardStack: Array<PageNavigationEntry>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PageNavigationEntry {
|
||||||
|
pageModuleName: string;
|
||||||
|
context?: any;
|
||||||
|
}
|
||||||
|
}
|
2
ui/frame/index.ts
Normal file
2
ui/frame/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
declare var module, require;
|
||||||
|
module.exports = require("ui/frame/frame");
|
@ -2,36 +2,23 @@
|
|||||||
import view = require("ui/core/view");
|
import view = require("ui/core/view");
|
||||||
import application = require("application");
|
import application = require("application");
|
||||||
|
|
||||||
|
var TEXT = "text";
|
||||||
|
|
||||||
|
// this is the name of the property to store text locally until attached to a valid Context
|
||||||
|
var TEXTPRIVATE = "_text";
|
||||||
|
|
||||||
export class Label extends view.View {
|
export class Label extends view.View {
|
||||||
private static textProperty = "text";
|
|
||||||
private _android: android.widget.TextView;
|
private _android: android.widget.TextView;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
// TODO: Verify that this is always true
|
|
||||||
var context = application.android.currentContext;
|
|
||||||
if (!context) {
|
|
||||||
// TODO: Delayed loading?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._android = new android.widget.TextView(context);
|
public onInitialized(context: android.content.Context) {
|
||||||
|
if (!this._android) {
|
||||||
var that = this;
|
// TODO: We need to decide whether we will support context switching and if yes - to implement it.
|
||||||
var textWatcher = new android.text.TextWatcher({
|
this.createUI(context);
|
||||||
beforeTextChanged: function (text: string, start: number, count: number, after: number) {
|
|
||||||
},
|
|
||||||
onTextChanged: function (text: string, start: number, before: number, count: number) {
|
|
||||||
},
|
|
||||||
afterTextChanged: function (editable: android.text.IEditable) {
|
|
||||||
//if (that.hasObservers(observable.Observable.propertyChangeEvent)) {
|
|
||||||
// var data = that.createPropertyChangeData(TextView.textProperty, that.text);
|
|
||||||
// that.notify(data);
|
|
||||||
//}
|
|
||||||
that.updateTwoWayBinding("text", editable.toString());
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
this._android.addTextChangedListener(textWatcher);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get android(): android.widget.TextView {
|
get android(): android.widget.TextView {
|
||||||
@ -39,17 +26,45 @@ export class Label extends view.View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get text(): string {
|
get text(): string {
|
||||||
|
if (!this._android) {
|
||||||
|
return this[TEXTPRIVATE];
|
||||||
|
}
|
||||||
return this._android.getText().toString();
|
return this._android.getText().toString();
|
||||||
}
|
}
|
||||||
set text(value: string) {
|
set text(value: string) {
|
||||||
this.setProperty(Label.textProperty, value);
|
this.setProperty(TEXT, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setNativeProperty(data: observable.PropertyChangeData) {
|
public setNativeProperty(data: observable.PropertyChangeData) {
|
||||||
// TODO: Will this be a gigantic if-else switch?
|
// TODO: Will this be a gigantic if-else switch?
|
||||||
if (data.propertyName === Label.textProperty) {
|
if (data.propertyName === TEXT) {
|
||||||
|
if (this._android) {
|
||||||
this._android.setText(data.value);
|
this._android.setText(data.value);
|
||||||
|
} else {
|
||||||
|
this[TEXTPRIVATE] = data.value;
|
||||||
|
}
|
||||||
} else if (true) {
|
} else if (true) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createUI(context: android.content.Context) {
|
||||||
|
this._android = new android.widget.TextView(context);
|
||||||
|
if (this[TEXTPRIVATE]) {
|
||||||
|
this._android.setText(this[TEXTPRIVATE]);
|
||||||
|
delete this[TEXTPRIVATE];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Do we need to listen for text change here?
|
||||||
|
//var that = this;
|
||||||
|
//var textWatcher = new android.text.TextWatcher({
|
||||||
|
// beforeTextChanged: function (text: string, start: number, count: number, after: number) {
|
||||||
|
// },
|
||||||
|
// onTextChanged: function (text: string, start: number, before: number, count: number) {
|
||||||
|
// },
|
||||||
|
// afterTextChanged: function (editable: android.text.IEditable) {
|
||||||
|
// that.updateTwoWayBinding("text", editable.toString());
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
//this._android.addTextChangedListener(textWatcher);
|
||||||
|
}
|
||||||
}
|
}
|
2
ui/pages/index.ts
Normal file
2
ui/pages/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
declare var module, require;
|
||||||
|
module.exports = require("ui/pages/page");
|
36
ui/pages/page-common.ts
Normal file
36
ui/pages/page-common.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import view = require("ui/core/view");
|
||||||
|
import dts = require("ui/pages");
|
||||||
|
import frame = require("ui/frame");
|
||||||
|
import application = require("application");
|
||||||
|
|
||||||
|
export class Page extends view.View implements dts.Page {
|
||||||
|
private _contentView: view.View;
|
||||||
|
private _frame: frame.Frame;
|
||||||
|
private _navigationContext: any;
|
||||||
|
|
||||||
|
public onLoaded: () => any;
|
||||||
|
|
||||||
|
get contentView(): view.View {
|
||||||
|
return this._contentView;
|
||||||
|
}
|
||||||
|
set contentView(value: view.View) {
|
||||||
|
this._contentView = value;
|
||||||
|
|
||||||
|
// TODO: Check if page is already loaded and update as needed
|
||||||
|
}
|
||||||
|
|
||||||
|
get frame(): frame.Frame {
|
||||||
|
return this._frame;
|
||||||
|
}
|
||||||
|
set frame(value: frame.Frame) {
|
||||||
|
// TODO: This method is called internally, check how to hide the setter from users.
|
||||||
|
this._frame = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onNavigatedTo(context: any) {
|
||||||
|
this._navigationContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onNavigatedFrom() {
|
||||||
|
}
|
||||||
|
}
|
81
ui/pages/page.android.ts
Normal file
81
ui/pages/page.android.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import definition = require("ui/pages");
|
||||||
|
import pageCommon = require("ui/pages/page-common");
|
||||||
|
|
||||||
|
export class Page extends pageCommon.Page {
|
||||||
|
private _android: AndroidPage;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._android = new AndroidPage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
get android(): definition.AndroidPage {
|
||||||
|
return this._android;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AndroidPage implements definition.AndroidPage {
|
||||||
|
private _ownerPage: definition.Page;
|
||||||
|
private _body: any;
|
||||||
|
private _activityExtends: any;
|
||||||
|
private _activity: android.app.Activity;
|
||||||
|
|
||||||
|
constructor(ownerPage: definition.Page) {
|
||||||
|
this._ownerPage = ownerPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
get activity(): android.app.Activity {
|
||||||
|
return this._activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
get activityBody(): any {
|
||||||
|
return this._body;
|
||||||
|
}
|
||||||
|
set activityBody(value: any) {
|
||||||
|
if (this._activityExtends) {
|
||||||
|
throw new Error("Activity already loaded and its body may not be changed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this._body = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getActivityExtends(): any {
|
||||||
|
if (!this._body) {
|
||||||
|
this.rebuildBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._activityExtends;
|
||||||
|
}
|
||||||
|
|
||||||
|
public resetBody() {
|
||||||
|
this._body = null;
|
||||||
|
this._activityExtends = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private rebuildBody() {
|
||||||
|
var that = this;
|
||||||
|
this._body = {
|
||||||
|
onCreate: function () {
|
||||||
|
that._activity = this;
|
||||||
|
this.super.onCreate(null);
|
||||||
|
|
||||||
|
var view = that._ownerPage.contentView;
|
||||||
|
if (view) {
|
||||||
|
// TODO: Notify the entire visual tree for being initialized
|
||||||
|
view.onInitialized(that._activity);
|
||||||
|
that._activity.setContentView(view.android);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._ownerPage.onLoaded) {
|
||||||
|
this._body.onStart = function () {
|
||||||
|
this.super.onStart();
|
||||||
|
that._ownerPage.onLoaded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._activityExtends = (<any>com).tns.NativeScriptActivity.extends(this._body);
|
||||||
|
}
|
||||||
|
}
|
25
ui/pages/page.d.ts
vendored
Normal file
25
ui/pages/page.d.ts
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
declare module "ui/pages" {
|
||||||
|
import view = require("ui/core/view");
|
||||||
|
import frame = require("ui/frame");
|
||||||
|
|
||||||
|
export class Page extends view.View {
|
||||||
|
contentView: view.View;
|
||||||
|
android: AndroidPage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Frame object controlling this instance.
|
||||||
|
*/
|
||||||
|
frame: frame.Frame;
|
||||||
|
|
||||||
|
onNavigatedTo(context: any): void;
|
||||||
|
onNavigatedFrom(): void;
|
||||||
|
|
||||||
|
onLoaded: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AndroidPage {
|
||||||
|
activity: android.app.Activity;
|
||||||
|
activityBody: any;
|
||||||
|
getActivityExtends(): any;
|
||||||
|
}
|
||||||
|
}
|
@ -20,11 +20,7 @@ export class TextInput extends view.View {
|
|||||||
onTextChanged: function (text: string, start: number, before: number, count: number) {
|
onTextChanged: function (text: string, start: number, before: number, count: number) {
|
||||||
},
|
},
|
||||||
afterTextChanged: function (editable: android.text.IEditable) {
|
afterTextChanged: function (editable: android.text.IEditable) {
|
||||||
//if (that.hasObservers(observable.Observable.propertyChangeEvent)) {
|
that.updateTwoWayBinding(TextInput.textProperty, editable.toString());
|
||||||
// var data = that.createPropertyChangeData(TextView.textProperty, that.text);
|
|
||||||
// that.notify(data);
|
|
||||||
//}
|
|
||||||
that.updateTwoWayBinding("text", editable.toString());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._android.addTextChangedListener(textWatcher);
|
this._android.addTextChangedListener(textWatcher);
|
1
ui/text-field/text-field.ios.ts
Normal file
1
ui/text-field/text-field.ios.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
Reference in New Issue
Block a user