diff --git a/CrossPlatformModules.csproj b/CrossPlatformModules.csproj
index eca1d024d..4d9d50f01 100644
--- a/CrossPlatformModules.csproj
+++ b/CrossPlatformModules.csproj
@@ -513,10 +513,6 @@
-
-
- containers.d.ts
-
utils.d.ts
diff --git a/apps/tests/pages/page17.xml b/apps/tests/pages/page17.xml
index fe7e9d1f2..a1bd0a0c2 100644
--- a/apps/tests/pages/page17.xml
+++ b/apps/tests/pages/page17.xml
@@ -1,7 +1,7 @@
-
-
+
+
diff --git a/apps/tests/ui/page/page-tests-common.ts b/apps/tests/ui/page/page-tests-common.ts
index ef04d515e..6daf6eac7 100644
--- a/apps/tests/ui/page/page-tests-common.ts
+++ b/apps/tests/ui/page/page-tests-common.ts
@@ -34,6 +34,73 @@ export function addLabelToPage(page: PageModule.Page, text?: string) {
page.content = label;
}
+export function test_menuItem_inherit_bindingContext() {
+
+ var page: PageModule.Page;
+ var label: LabelModule.Label;
+ var context = { text: "item" };
+
+ var pageFactory = function (): PageModule.Page {
+ page = new PageModule.Page();
+ page.bindingContext = context;
+ var menuItem = new PageModule.MenuItem();
+
+ menuItem.bind({
+ sourceProperty: "text",
+ targetProperty: "text"
+ });
+
+ page.optionsMenu.addItem(menuItem);
+
+ label = new LabelModule.Label();
+ label.text = "Text";
+ page.content = label;
+ return page;
+ };
+
+ helper.navigate(pageFactory);
+
+ try {
+ TKUnit.assertEqual(page.optionsMenu.getItemAt(0).text, "item", "menuItem.text should equal to 'item'");
+ }
+ finally {
+ helper.goBack();
+ }
+}
+
+export function test_Setting_OptionsMenu_doesnt_thrown() {
+
+ var page: PageModule.Page;
+ var label: LabelModule.Label;
+ var gotException = false;
+
+ var pageFactory = function (): PageModule.Page {
+ page = new PageModule.Page();
+ var menuItem = new PageModule.MenuItem();
+ menuItem.text = "Item";
+ page.optionsMenu.addItem(menuItem);
+
+ label = new LabelModule.Label();
+ label.text = "Text";
+ page.content = label;
+ return page;
+ };
+
+ try {
+ helper.navigate(pageFactory);
+ }
+ catch (e) {
+ gotException = true;
+ }
+
+ try {
+ TKUnit.assert(!gotException, "Expected: false, Actual: " + gotException);
+ }
+ finally {
+ helper.goBack();
+ }
+}
+
export function test_AfterPageLoaded_is_called_NativeInstance_is_created() {
var page: PageModule.Page;
diff --git a/apps/tests/ui/page/page-tests.ios.ts b/apps/tests/ui/page/page-tests.ios.ts
index 8d8cdee26..8c035dafe 100644
--- a/apps/tests/ui/page/page-tests.ios.ts
+++ b/apps/tests/ui/page/page-tests.ios.ts
@@ -3,11 +3,12 @@ import PageModule = require("ui/page");
import TKUnit = require("../../TKUnit");
import LabelModule = require("ui/label");
import helper = require("../helper");
+import view = require("ui/core/view");
declare var exports;
require("utils/module-merge").merge(PageTestCommon, exports);
-export var test_NavigateToNewPage_InnerControl = function () {
+export function test_NavigateToNewPage_InnerControl() {
var testPage: PageModule.Page;
var pageFactory = function (): PageModule.Page {
testPage = new PageModule.Page();
@@ -24,3 +25,38 @@ export var test_NavigateToNewPage_InnerControl = function () {
TKUnit.assert(label.android === undefined, "InnerControl.android should be undefined after navigate back.");
TKUnit.assert(label.isLoaded === false, "InnerControl.isLoaded should become false after navigating back");
}
+
+export function test_NavBar_isVisible_when_MenuItems_areSet() {
+
+ var page: PageModule.Page;
+ var label: LabelModule.Label;
+ var navBarIsVisible = false;
+
+ var handler = function (data) {
+ page.off(view.knownEvents.loaded, handler);
+ navBarIsVisible = (page.frame.ios).showNavigationBar;
+ }
+
+ var pageFactory = function (): PageModule.Page {
+ page = new PageModule.Page();
+ page.on(view.knownEvents.loaded, handler);
+
+ var mi = new PageModule.MenuItem();
+ mi.text = "B";
+ page.optionsMenu.addItem(mi);
+ label = new LabelModule.Label();
+ label.text = "Text";
+ page.content = label;
+ return page;
+ };
+
+ helper.navigate(pageFactory);
+
+ try {
+ TKUnit.assert(navBarIsVisible, "Expected: true, Actual: " + navBarIsVisible);
+ }
+ finally {
+ page.off(view.knownEvents.loaded, handler);
+ helper.goBack();
+ }
+}
\ No newline at end of file
diff --git a/ui/builder/component-builder.ts b/ui/builder/component-builder.ts
index 86d8f4e6c..5f612bf1e 100644
--- a/ui/builder/component-builder.ts
+++ b/ui/builder/component-builder.ts
@@ -66,7 +66,7 @@ export function getComponentModule(elementName: string, namespace: string, attri
// Create instance of the component.
instance = new instanceType();
} catch (ex) {
- throw new Error("Cannot create module " + moduleId + ". " + ex);
+ throw new Error("Cannot create module " + moduleId + ". " + ex + ". StackTrace: " + ex.stack);
}
if (instance && instanceModule) {
diff --git a/ui/button/button.ios.ts b/ui/button/button.ios.ts
index 02fd85aed..e0d8df868 100644
--- a/ui/button/button.ios.ts
+++ b/ui/button/button.ios.ts
@@ -20,7 +20,6 @@ class TapHandlerImpl extends NSObject {
public static ObjCExposedMethods = {
"tap": { returns: interop.types.void, params: [interop.types.id] }
};
-
}
// merge the exports of the common file with the exports of this file
diff --git a/ui/enums/enums.d.ts b/ui/enums/enums.d.ts
index 4d736060b..ca2dc60f8 100644
--- a/ui/enums/enums.d.ts
+++ b/ui/enums/enums.d.ts
@@ -9,25 +9,25 @@
* iOS: [UIKeyboardTypeNumbersAndPunctuation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIKeyboardType)
*/
export var datetime: string;
-
+
/**
* Android: [TYPE_CLASS_PHONE](http://developer.android.com/reference/android/text/InputType.html#TYPE_CLASS_PHONE)
* iOS: [UIKeyboardTypePhonePad](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIKeyboardType)
*/
export var phone: string;
-
+
/**
* Android: [TYPE_CLASS_NUMBER](http://developer.android.com/reference/android/text/InputType.html#TYPE_CLASS_NUMBER) | android.text.InputType.TYPE_NUMBER_VARIATION_NORMAL | [TYPE_NUMBER_FLAG_SIGNED](http://developer.android.com/reference/android/text/InputType.html#TYPE_NUMBER_FLAG_SIGNED) | [TYPE_NUMBER_FLAG_DECIMAL](http://developer.android.com/reference/android/text/InputType.html#TYPE_NUMBER_FLAG_DECIMAL)
* iOS: [UIKeyboardTypeNumbersAndPunctuation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIKeyboardType)
*/
export var number: string;
-
+
/**
* Android: [TYPE_CLASS_TEXT](http://developer.android.com/reference/android/text/InputType.html#TYPE_CLASS_TEXT) | [TYPE_TEXT_VARIATION_URI](http://developer.android.com/reference/android/text/InputType.html#TYPE_TEXT_VARIATION_URI)
* iOS: [UIKeyboardTypeURL](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIKeyboardType)
*/
export var url: string;
-
+
/**
* Android: [TYPE_CLASS_TEXT](http://developer.android.com/reference/android/text/InputType.html#TYPE_CLASS_TEXT) | [TYPE_TEXT_VARIATION_EMAIL_ADDRESS](http://developer.android.com/reference/android/text/InputType.html#TYPE_TEXT_VARIATION_EMAIL_ADDRESS)
* iOS: [UIKeyboardTypeEmailAddress](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIKeyboardType)
@@ -56,13 +56,13 @@
* iOS: [UIReturnKeyGo](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIReturnKeyType)
*/
export var go: string;
-
+
/**
* Android: [IME_ACTION_SEARCH](http://developer.android.com/reference/android/view/inputmethod/EditorInfo.html#IME_ACTION_SEARCH)
* iOS: [UIReturnKeySearch](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIReturnKeyType)
*/
export var search: string;
-
+
/**
* Android: [IME_ACTION_SEND](http://developer.android.com/reference/android/view/inputmethod/EditorInfo.html#IME_ACTION_SEND)
* iOS: [UIReturnKeySend](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIReturnKeyType)
@@ -304,7 +304,7 @@
* Capitalize the first letter of each sentence automatically.
*/
export var sentences: string;
-
+
/**
* Capitalize all characters automatically.
*/
@@ -325,4 +325,44 @@
*/
export var jpeg: string;
}
-}
+
+ /**
+ * Specifies NavigationBar visibility mode.
+ */
+ module NavigationBarVisibility {
+ /**
+ * NavigationBar will be visible if there if frame backstack canGoBack is true or Page have optionsMenu with menuItems.
+ */
+ export var auto: string;
+
+ /**
+ * NavigationBar will be hidden.
+ */
+ export var never: string;
+
+ /**
+ * NavigationBar will be visible.
+ */
+ export var always: string;
+ }
+
+ /**
+ * Specifies android MenuItem position.
+ */
+ module MenuItemPosition {
+ /**
+ * Always show this item as a button in an Action Bar.
+ */
+ export var actionBar: string;
+
+ /**
+ * Show this item as a button in an Action Bar if the system decides there is room for it.
+ */
+ export var actionBarIfRoom: string;
+
+ /**
+ * Never show this item as a button in an Action Bar.
+ */
+ export var popup: string;
+ }
+}
\ No newline at end of file
diff --git a/ui/enums/enums.ts b/ui/enums/enums.ts
index 1e0547bf9..d88744313 100644
--- a/ui/enums/enums.ts
+++ b/ui/enums/enums.ts
@@ -86,7 +86,19 @@ export module AutocapitalizationType {
export var allCharacters: string = "allCharacters";
}
+export module NavigationBarVisibility {
+ export var auto: string = "auto";
+ export var never: string = "never";
+ export var always: string = "always";
+}
+
+export module MenuItemPosition {
+ export var actionBar: string = "actionBar";
+ export var actionBarIfRoom: string = "actionBarIfRoom";
+ export var popup: string = "popup";
+}
+
export module ImageFormat {
export var png: string = "png";
export var jpeg: string = "jpeg";
-}
+}
\ No newline at end of file
diff --git a/ui/frame/frame-common.ts b/ui/frame/frame-common.ts
index 7122f7d76..a569761a6 100644
--- a/ui/frame/frame-common.ts
+++ b/ui/frame/frame-common.ts
@@ -270,7 +270,7 @@ export class Frame extends view.CustomLayoutView implements definition.Frame {
}
get backStack(): Array {
- return this._backStack;
+ return this._backStack.slice();
}
get currentPage(): pages.Page {
diff --git a/ui/frame/frame.android.ts b/ui/frame/frame.android.ts
index dee5d7fc6..412a992c6 100644
--- a/ui/frame/frame.android.ts
+++ b/ui/frame/frame.android.ts
@@ -7,6 +7,7 @@ import utils = require("utils/utils");
import view = require("ui/core/view");
import application = require("application");
import imageSource = require("image-source");
+import enums = require("ui/enums");
declare var exports;
require("utils/module-merge").merge(frameCommon, exports);
@@ -143,14 +144,29 @@ class PageFragmentBody extends android.app.Fragment {
for (var i = 0; i < items.length; i++) {
var item = items[i];
- var menuItem = menu.add(android.view.Menu.NONE, i, item.priority, item.text);
+ var menuItem = menu.add(android.view.Menu.NONE, i, android.view.Menu.NONE, item.text);
if (item.icon) {
- var img = imageSource.fromFile(item.icon);
+ var img = imageSource.fromResource(item.icon);
var drawable = new android.graphics.drawable.BitmapDrawable(img.android);
menuItem.setIcon(drawable);
}
- menuItem.setShowAsAction(android.view.MenuItem.SHOW_AS_ACTION_ALWAYS);
+ var showAsAction = PageFragmentBody.getShowAsAction(item);
+ menuItem.setShowAsAction(showAsAction);
+ }
+ }
+
+ private static getShowAsAction(menuItem: pages.MenuItem): number {
+ switch (menuItem.android.position) {
+ case enums.MenuItemPosition.actionBarIfRoom:
+ return android.view.MenuItem.SHOW_AS_ACTION_IF_ROOM;
+
+ case enums.MenuItemPosition.popup:
+ return android.view.MenuItem.SHOW_AS_ACTION_NEVER;
+
+ case enums.MenuItemPosition.actionBar:
+ default:
+ return android.view.MenuItem.SHOW_AS_ACTION_ALWAYS;
}
}
@@ -462,7 +478,7 @@ class NativeActivity extends com.tns.NativeScriptActivity {
trace.write("NativeScriptActivity.onDestroy();", trace.categories.NativeLifecycle);
}
- onOptionsItemSelected(menuItem) {
+ onOptionsItemSelected(menuItem: android.view.IMenuItem) {
if (!this.androidFrame.hasListeners(frameCommon.knownEvents.android.optionSelected)) {
return false;
}
@@ -638,10 +654,11 @@ function findPageForFragment(fragment: android.app.Fragment, frame: Frame) {
trace.write("Current page matches fragment: " + fragmentTag, trace.categories.NativeLifecycle);
}
else {
- for (var i = 0; i < frame.backStack.length; i++) {
- entry = frame.backStack[i];
- if (frame.backStack[i].resolvedPage[TAG] === fragmentTag) {
- entry = frame.backStack[i];
+ var backStack = frame.backStack;
+ for (var i = 0; i < backStack.length; i++) {
+ entry = backStack[i];
+ if (backStack[i].resolvedPage[TAG] === fragmentTag) {
+ entry = backStack[i];
break;
}
}
diff --git a/ui/frame/frame.d.ts b/ui/frame/frame.d.ts
index 880c82567..9ddf69a6f 100644
--- a/ui/frame/frame.d.ts
+++ b/ui/frame/frame.d.ts
@@ -145,7 +145,7 @@ declare module "ui/frame" {
/**
* Gets the Android-specific menu item that has been selected.
*/
- item: android.view.MenuItem;
+ item: android.view.IMenuItem;
/**
* True to mark the event as handled (that is to prevent the default processing).
@@ -207,6 +207,12 @@ declare module "ui/frame" {
* Gets the native [UINavigationController](https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UINavigationController_Class/index.html) instance associated with this Frame.
*/
controller: UINavigationController;
+
+ /**
+ * Gets or sets the visibility of navigationBar.
+ * Use NavBarVisibility enumeration - auto, never, always
+ */
+ navBarVisibility: string;
}
/**
diff --git a/ui/frame/frame.ios.ts b/ui/frame/frame.ios.ts
index a6019ea8f..c018cc505 100644
--- a/ui/frame/frame.ios.ts
+++ b/ui/frame/frame.ios.ts
@@ -1,6 +1,9 @@
import frameCommon = require("ui/frame/frame-common");
import definition = require("ui/frame");
import trace = require("trace");
+import imageSource = require("image-source");
+import pages = require("ui/page");
+import enums = require("ui/enums");
declare var exports;
require("utils/module-merge").merge(frameCommon, exports);
@@ -12,6 +15,7 @@ var navDepth = 0;
export class Frame extends frameCommon.Frame {
private _ios: iOSFrame;
private _paramToNavigate: any;
+ public shouldSkipNativePop: boolean = false;
constructor() {
super();
@@ -35,7 +39,7 @@ export class Frame extends frameCommon.Frame {
this._paramToNavigate = param;
}
}
-
+
public _navigateCore(backstackEntry: definition.BackstackEntry) {
var viewController = backstackEntry.resolvedPage.ios;
if (!viewController) {
@@ -47,9 +51,7 @@ export class Frame extends frameCommon.Frame {
animated = this._getIsAnimatedNavigation(backstackEntry.entry);
}
- if (this.backStack.length > 0) {
- this._ios.showNavigationBar = true;
- }
+ this.updateNavigationBar();
viewController[ENTRY] = backstackEntry;
@@ -61,17 +63,29 @@ export class Frame extends frameCommon.Frame {
public _goBackCore(entry: definition.NavigationEntry) {
navDepth--;
trace.write("Frame<" + this._domId + ">.popViewControllerAnimated depth = " + navDepth, trace.categories.Navigation);
-
- this._ios.controller.allowPop = true;
- this._ios.controller.popViewControllerAnimated(this._getIsAnimatedNavigation(entry));
- this._ios.controller.allowPop = false;
-
- if (this.backStack.length === 0) {
- this._ios.showNavigationBar = false;
+ if (!this.shouldSkipNativePop) {
+ this._ios.controller.popViewControllerAnimated(this._getIsAnimatedNavigation(entry));
}
}
- public get ios(): any {
+ public updateNavigationBar(page?: pages.Page): void {
+ switch (this._ios.navBarVisibility) {
+ case enums.NavigationBarVisibility.always:
+ this._ios.showNavigationBar = true;
+ break;
+
+ case enums.NavigationBarVisibility.never:
+ this._ios.showNavigationBar = false;
+ break;
+
+ case enums.NavigationBarVisibility.auto:
+ var pageInstance: pages.Page = page || this.currentPage;
+ this._ios.showNavigationBar = this.backStack.length > 0 || (pageInstance && pageInstance.optionsMenu.getItems().length > 0);
+ break;
+ }
+ }
+
+ public get ios(): iOSFrame {
return this._ios;
}
@@ -122,9 +136,41 @@ export class Frame extends frameCommon.Frame {
var navigationBar = this._ios.controller.navigationBar;
return (navigationBar && !this._ios.controller.navigationBarHidden) ? navigationBar.frame.size.height : 0;
}
+
+ public _invalidateOptionsMenu() {
+ this.populateMenuItems(this.currentPage);
+ }
+
+ populateMenuItems(page: pages.Page) {
+ var items = page.optionsMenu.getItems();
+
+ var navigationItem: UINavigationItem = (page.ios).navigationItem;
+ var array: NSMutableArray = items.length > 0 ? NSMutableArray.new() : null;
+
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ var tapHandler = TapBarItemHandlerImpl.new().initWithOwner(item);
+ // associate handler with menuItem or it will get collected by JSC.
+ (item).handler = tapHandler;
+
+ var barButtonItem: UIBarButtonItem;
+ if (item.icon) {
+ var img = imageSource.fromResource(item.icon);
+ barButtonItem = UIBarButtonItem.alloc().initWithImageStyleTargetAction(img.ios, UIBarButtonItemStyle.UIBarButtonItemStylePlain, tapHandler, "tap");
+ }
+ else {
+ barButtonItem = UIBarButtonItem.alloc().initWithTitleStyleTargetAction(item.text, UIBarButtonItemStyle.UIBarButtonItemStylePlain, tapHandler, "tap");
+ }
+
+ array.addObject(barButtonItem);
+ }
+
+ if (array) {
+ navigationItem.setRightBarButtonItemsAnimated(array, true);
+ }
+ }
}
-/* tslint:disable */
class UINavigationControllerImpl extends UINavigationController implements UINavigationControllerDelegate {
public static ObjCProtocols = [UINavigationControllerDelegate];
@@ -132,21 +178,13 @@ class UINavigationControllerImpl extends UINavigationController implements UINav
return super.new();
}
- private _owner: frameCommon.Frame;
-
- public initWithOwner(owner: frameCommon.Frame): UINavigationControllerImpl {
+ private _owner: Frame;
+
+ public initWithOwner(owner: Frame): UINavigationControllerImpl {
this._owner = owner;
return this;
}
- private _allowPop: boolean;
- public get allowPop(): boolean {
- return this._allowPop;
- }
- public set allowPop(value: boolean) {
- this._allowPop = value;
- }
-
public viewDidLoad(): void {
this.view.autoresizesSubviews = false;
this.view.autoresizingMask = UIViewAutoresizing.UIViewAutoresizingNone;
@@ -158,39 +196,37 @@ class UINavigationControllerImpl extends UINavigationController implements UINav
this._owner._updateLayout();
}
- public popViewControllerAnimated(animated: boolean): UIViewController {
- if (this.allowPop) {
- return super.popViewControllerAnimated(animated);
- }
- else {
- var currentControler = this._owner.currentPage.ios;
- this._owner.goBack();
- return currentControler;
- }
- }
+ public navigationControllerDidShowViewControllerAnimated(navigationController: UINavigationController, viewController: UIViewController, animated: boolean): void {
+
+ var frame: Frame = this._owner;
+ var backStack = frame.backStack;
+ var currentEntry = backStack.length > 0 ? backStack[backStack.length - 1] : null;
+ var newEntry: definition.BackstackEntry = viewController[ENTRY];
+
+ if (newEntry === currentEntry && currentEntry) {
+ try {
+ frame.shouldSkipNativePop = true;
+ frame.goBack();
+ }
+ finally {
+ frame.shouldSkipNativePop = false;
+ }
+ }
- public navigationControllerWillShowViewControllerAnimated(navigationController: UINavigationController, viewController: UIViewController, animated: boolean): void {
- var frame = this._owner;
var page = frame.currentPage;
if (page) {
frame._removeView(page);
}
- var newEntry: definition.BackstackEntry = viewController[ENTRY];
var newPage = newEntry.resolvedPage;
frame._currentEntry = newEntry;
frame._addView(newPage);
-
+ frame.populateMenuItems(newPage);
+ frame.updateNavigationBar();
+
// notify the page
newPage.onNavigatedTo(newEntry.entry.context);
- }
-
- public navigationControllerDidShowViewControllerAnimated(navigationController: UINavigationController, viewController: UIViewController, animated: boolean): void {
- var frame: frameCommon.Frame = this._owner;
- var newEntry: definition.BackstackEntry = viewController[ENTRY];
- var newPage = newEntry.resolvedPage;
-
frame._processNavigationQueue(newPage);
}
@@ -199,16 +235,19 @@ class UINavigationControllerImpl extends UINavigationController implements UINav
}
}
+/* tslint:disable */
class iOSFrame implements definition.iOSFrame {
- /* tslint:enable */
+/* tslint:enable */
private _controller: UINavigationControllerImpl;
private _showNavigationBar: boolean;
+ private _navBarVisibility: string;
- constructor(owner: frameCommon.Frame) {
+ constructor(owner: Frame) {
this._controller = UINavigationControllerImpl.new().initWithOwner(owner);
this._controller.delegate = this._controller;
this._controller.automaticallyAdjustsScrollViewInsets = false;
this.showNavigationBar = false;
+ this._navBarVisibility = enums.NavigationBarVisibility.auto;
}
public get controller() {
@@ -222,4 +261,32 @@ class iOSFrame implements definition.iOSFrame {
this._showNavigationBar = value;
this._controller.navigationBarHidden = !value;
}
-}
\ No newline at end of file
+
+ public get navBarVisibility(): string {
+ return this._navBarVisibility;
+ }
+ public set navBarVisibility(value: string) {
+ this._navBarVisibility = value;
+ }
+}
+
+class TapBarItemHandlerImpl extends NSObject {
+ static new(): TapBarItemHandlerImpl {
+ return super.new();
+ }
+
+ private _owner: pages.MenuItem;
+
+ public initWithOwner(owner: pages.MenuItem): TapBarItemHandlerImpl {
+ this._owner = owner;
+ return this;
+ }
+
+ public tap(args) {
+ this._owner._raiseTap();
+ }
+
+ public static ObjCExposedMethods = {
+ "tap": { returns: interop.types.void, params: [interop.types.id] }
+ };
+}
\ No newline at end of file
diff --git a/ui/layouts/absolute-layout/absolute-layout.d.ts b/ui/layouts/absolute-layout/absolute-layout.d.ts
index 4580d4319..541950f18 100644
--- a/ui/layouts/absolute-layout/absolute-layout.d.ts
+++ b/ui/layouts/absolute-layout/absolute-layout.d.ts
@@ -1,12 +1,23 @@
declare module "ui/layouts/absolute-layout" {
import layout = require("ui/layouts/layout");
import view = require("ui/core/view");
+ import dependencyObservable = require("ui/core/dependency-observable");
/**
* A layout that lets you specify exact locations (left/top coordinates) of its children.
*/
class AbsoluteLayout extends layout.Layout {
+ /**
+ * Represents the observable property backing the left property.
+ */
+ public static leftProperty: dependencyObservable.Property;
+
+ /**
+ * Represents the observable property backing the top property.
+ */
+ public static topProperty: dependencyObservable.Property;
+
/**
* Gets the value of the Left property from a given View.
*/
diff --git a/ui/layouts/absolute-layout/absolute-layout.ts b/ui/layouts/absolute-layout/absolute-layout.ts
index f126d4b47..cd311b673 100644
--- a/ui/layouts/absolute-layout/absolute-layout.ts
+++ b/ui/layouts/absolute-layout/absolute-layout.ts
@@ -17,10 +17,10 @@ function onPropertyChanged(data: dependencyObservable.PropertyChangeData) {
export class AbsoluteLayout extends layouts.Layout implements definition.AbsoluteLayout {
- public static LeftProperty = new dependencyObservable.Property("Left", "AbsoluteLayout",
+ public static leftProperty = new dependencyObservable.Property("left", "AbsoluteLayout",
new dependencyObservable.PropertyMetadata(0, undefined, onPropertyChanged, numberUtils.isFiniteNumber));
- public static TopProperty = new dependencyObservable.Property("Top", "AbsoluteLayout",
+ public static topProperty = new dependencyObservable.Property("top", "AbsoluteLayout",
new dependencyObservable.PropertyMetadata(0, undefined, onPropertyChanged, numberUtils.isFiniteNumber));
public static getLeft(element: view.View): number {
@@ -28,14 +28,14 @@ export class AbsoluteLayout extends layouts.Layout implements definition.Absolut
throw new Error("element cannot be null or undefinied.");
}
- return element._getValue(AbsoluteLayout.LeftProperty);
+ return element._getValue(AbsoluteLayout.leftProperty);
}
public static setLeft(element: view.View, value: number): void {
if (!element) {
throw new Error("element cannot be null or undefinied.");
}
- element._setValue(AbsoluteLayout.LeftProperty, value);
+ element._setValue(AbsoluteLayout.leftProperty, value);
}
public static getTop(element: view.View): number {
@@ -43,14 +43,14 @@ export class AbsoluteLayout extends layouts.Layout implements definition.Absolut
throw new Error("element cannot be null or undefinied.");
}
- return element._getValue(AbsoluteLayout.TopProperty);
+ return element._getValue(AbsoluteLayout.topProperty);
}
public static setTop(element: view.View, value: number): void {
if (!element) {
throw new Error("element cannot be null or undefinied.");
}
- element._setValue(AbsoluteLayout.TopProperty, value);
+ element._setValue(AbsoluteLayout.topProperty, value);
}
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
diff --git a/ui/page/page-common.ts b/ui/page/page-common.ts
index 3dcf09a53..e614c8101 100644
--- a/ui/page/page-common.ts
+++ b/ui/page/page-common.ts
@@ -6,7 +6,9 @@ import styleScope = require("ui/styling/style-scope");
import fs = require("file-system");
import fileSystemAccess = require("file-system/file-system-access");
import trace = require("trace");
-import observable = require("data/observable");
+import bindable = require("ui/core/bindable");
+import dependencyObservable = require("ui/core/dependency-observable");
+import enums = require("ui/enums");
var OPTIONS_MENU = "optionsMenu";
@@ -171,6 +173,12 @@ export class OptionsMenu implements dts.OptionsMenu {
}
this._items.push(item);
+ item.menu = this;
+ item.bind({
+ sourceProperty: "bindingContext",
+ targetProperty: "bindingContext"
+ }, this._page);
+
this.invalidate();
}
@@ -184,6 +192,8 @@ export class OptionsMenu implements dts.OptionsMenu {
throw new Error("Cannot find item to remove");
}
+ item.menu = undefined;
+ item.unbind("bindingContext");
this._items.splice(itemIndex, 1);
this.invalidate();
}
@@ -201,19 +211,60 @@ export class OptionsMenu implements dts.OptionsMenu {
this.invalidate();
}
- private invalidate() {
+ invalidate() {
if (this._page.frame) {
this._page.frame._invalidateOptionsMenu();
}
}
}
-export class MenuItem extends observable.Observable implements dts.MenuItem {
- public text: string = "";
- public icon: string;
- public priority: number = 0;
+export class MenuItem extends bindable.Bindable implements dts.MenuItem {
+
+ public static textProperty = new dependencyObservable.Property(
+ "text", "MenuItem", new dependencyObservable.PropertyMetadata("", null, MenuItem.onItemChanged));
+
+ public static iconProperty = new dependencyObservable.Property(
+ "icon", "MenuItem", new dependencyObservable.PropertyMetadata(null, null, MenuItem.onItemChanged));
+
+ private static onItemChanged(data: dependencyObservable.PropertyChangeData) {
+ var menuItem =