diff --git a/apps/tests/TKUnit.ts b/apps/tests/TKUnit.ts index 0ec900df9..04e719afa 100644 --- a/apps/tests/TKUnit.ts +++ b/apps/tests/TKUnit.ts @@ -177,6 +177,12 @@ export function assertTrue(test: boolean, message?: string) { } }; +export function assertFalse(test: boolean, message?: string) { + if (test !== false) { + throw new Error(message); + } +}; + export function assertNotEqual(actual: any, expected: any, message?: string) { var equals = false; @@ -223,6 +229,12 @@ export function assertNull(actual: any, message?: string) { } }; +export function assertNotNull(actual: any, message?: string) { + if (actual === null || actual === undefined) { + throw new Error(message + " Actual: " + actual + " is null/undefined"); + } +}; + export function areClose(actual: number, expected: number, delta: number): boolean { if (isNaN(actual) || Math.abs(actual - expected) > delta) { return false; diff --git a/apps/tests/ui/action-bar/action-bar-tests-common.ts b/apps/tests/ui/action-bar/action-bar-tests-common.ts index 75e9cc558..164e4b931 100644 --- a/apps/tests/ui/action-bar/action-bar-tests-common.ts +++ b/apps/tests/ui/action-bar/action-bar-tests-common.ts @@ -313,4 +313,20 @@ export function test_Setting_ActionItemsWithNumberAsText_doesnt_thrown() { finally { helper.goBack(); } +} + +export function createPageAndNavigate() { + var page: PageModule.Page; + var pageFactory = function (): PageModule.Page { + page = new PageModule.Page(); + + var label = new LabelModule.Label(); + label.text = "Text"; + page.content = label; + return page; + }; + + helper.navigate(pageFactory); + + return page; } \ No newline at end of file diff --git a/apps/tests/ui/action-bar/action-bar-tests.android.ts b/apps/tests/ui/action-bar/action-bar-tests.android.ts index 3e38a9296..caf0caf56 100644 --- a/apps/tests/ui/action-bar/action-bar-tests.android.ts +++ b/apps/tests/ui/action-bar/action-bar-tests.android.ts @@ -1,2 +1,45 @@ import actionTestsCommon = require("./action-bar-tests-common"); -global.moduleMerge(actionTestsCommon, exports); \ No newline at end of file +import helper = require("../helper"); +import TKUnit = require("../../TKUnit"); +import { ActionItem } from "ui/action-bar"; +import { Visibility } from "ui/enums"; +import fs = require("file-system"); + +global.moduleMerge(actionTestsCommon, exports); + +export function test_actionItem_visibility() { + var actionItem = new ActionItem(); + actionItem.text = "Test"; + var page = actionTestsCommon.createPageAndNavigate(); + try { + page.actionBar.actionItems.addItem(actionItem); + var toolbar = (page.actionBar)._toolbar; + var menu = toolbar.getMenu(); + + TKUnit.assertTrue(menu.hasVisibleItems(), "Visibility does not work"); + actionItem.visibility = Visibility.collapse; + TKUnit.assertFalse(menu.hasVisibleItems(), "Visibility does not work"); + } + finally { + helper.goBack(); + } +} + +export function test_navigationButton_visibility() { + var actionItem = new ActionItem(); + actionItem.icon = "~/small-image.png"; + var page = actionTestsCommon.createPageAndNavigate(); + try { + page.actionBar.navigationButton = actionItem; + + var toolbar = (page.actionBar)._toolbar; + var menu = toolbar.getMenu(); + + TKUnit.assertNotNull(toolbar.getNavigationIcon(), "Visibility does not work"); + actionItem.visibility = Visibility.collapse; + TKUnit.assertNull(toolbar.getNavigationIcon(), "Visibility does not work"); + } + finally { + helper.goBack(); + } +} \ No newline at end of file diff --git a/apps/tests/ui/action-bar/action-bar-tests.ios.ts b/apps/tests/ui/action-bar/action-bar-tests.ios.ts index 3b4487495..6182b6151 100644 --- a/apps/tests/ui/action-bar/action-bar-tests.ios.ts +++ b/apps/tests/ui/action-bar/action-bar-tests.ios.ts @@ -5,9 +5,12 @@ import LabelModule = require("ui/label"); import helper = require("../helper"); import view = require("ui/core/view"); import actionBar = require("ui/action-bar"); +import { Visibility } from "ui/enums"; global.moduleMerge(actionTestsCommon, exports); +var ASYNC = 0.2; + export function test_NavBar_isVisible_when_MenuItems_areSet() { var page: PageModule.Page; @@ -80,4 +83,58 @@ export function test_NavBarItemsAreClearedFromNativeWhenClearedFromNativeScript( page.off(view.View.loadedEvent, handler); helper.goBack(); } +} + +export function test_actionItem_visibility() { + var actionItem = new actionBar.ActionItem(); + actionItem.text = "Test"; + actionItem.ios.position = "left"; + var page = actionTestsCommon.createPageAndNavigate(); + + try { + page.actionBar.actionItems.addItem(actionItem); + + var viewController = (page.ios); + var navigationItem: UINavigationItem = viewController.navigationItem; + + var leftBarButtonItemsCount = navigationItem.leftBarButtonItems ? navigationItem.leftBarButtonItems.count : 0; + TKUnit.assertEqual(leftBarButtonItemsCount, 1, "Visibility does not work"); + actionItem.visibility = Visibility.collapse; + + TKUnit.waitUntilReady(() => { + leftBarButtonItemsCount = navigationItem.leftBarButtonItems ? navigationItem.leftBarButtonItems.count : 0; + + return leftBarButtonItemsCount === 0; + }); + + leftBarButtonItemsCount = navigationItem.leftBarButtonItems ? navigationItem.leftBarButtonItems.count : 0; + TKUnit.assertEqual(leftBarButtonItemsCount, 0, "Visibility does not work"); + } + finally { + helper.goBack(); + } +} + +export function test_navigationButton_visibility() { + var actionItem = new actionBar.ActionItem(); + actionItem.text = "Test"; + var page = actionTestsCommon.createPageAndNavigate(); + try { + page.actionBar.navigationButton = actionItem; + + var viewController = (page.ios); + var navigationItem: UINavigationItem = viewController.navigationItem; + + TKUnit.assertFalse(navigationItem.hidesBackButton, "Visibility does not work"); + actionItem.visibility = Visibility.collapse; + + TKUnit.waitUntilReady(() => { + return navigationItem.hidesBackButton; + }); + + TKUnit.assertTrue(navigationItem.hidesBackButton, "Visibility does not work"); + } + finally { + helper.goBack(); + } } \ No newline at end of file diff --git a/ui/action-bar/action-bar-common.ts b/ui/action-bar/action-bar-common.ts index 9c742e035..26d4a0823 100644 --- a/ui/action-bar/action-bar-common.ts +++ b/ui/action-bar/action-bar-common.ts @@ -21,7 +21,7 @@ function onTitlePropertyChanged(data: dependencyObservable.PropertyChangeData) { export class ActionBar extends view.View implements dts.ActionBar { public static titleProperty = new dependencyObservable.Property("title", "ActionBar", new proxy.PropertyMetadata(undefined, dependencyObservable.PropertyMetadataSettings.None, onTitlePropertyChanged)); - + private _actionItems: ActionItems; private _navigationButton: dts.NavigationButton; private _page: pages.Page; @@ -200,6 +200,17 @@ export class ActionItems implements dts.ActionItems { return this._items.slice(); } + public getVisibleItems(): Array { + var visibleItems = []; + this._items.forEach((item) => { + if (isVisible(item)) { + visibleItems.push(item); + } + }); + + return visibleItems; + } + public getItemAt(index: number): dts.ActionItem { if (index < 0 || index >= this._items.length) { return undefined; @@ -238,16 +249,15 @@ export class ActionItem extends bindable.Bindable implements dts.ActionItem { public static iconProperty = new dependencyObservable.Property( "icon", "ActionItem", new dependencyObservable.PropertyMetadata(null, null, ActionItem.onItemChanged)); - private static onItemChanged(data: dependencyObservable.PropertyChangeData) { - var menuItem = data.object; - if (menuItem.actionBar) { - menuItem.actionBar.update(); - } - } + public static visibilityProperty = new dependencyObservable.Property( + "visibility", "ActionItemBase", new dependencyObservable.PropertyMetadata(enums.Visibility.visible, null, ActionItem.onItemChanged)); + + private _actionBar: ActionBar; get text(): string { return this._getValue(ActionItem.textProperty); } + set text(value: string) { this._setValue(ActionItem.textProperty, value); } @@ -255,14 +265,23 @@ export class ActionItem extends bindable.Bindable implements dts.ActionItem { get icon(): string { return this._getValue(ActionItem.iconProperty); } + set icon(value: string) { this._setValue(ActionItem.iconProperty, value); } - private _actionBar: ActionBar; + get visibility(): string { + return this._getValue(ActionItem.visibilityProperty); + } + + set visibility(value: string) { + this._setValue(ActionItem.visibilityProperty, value); + } + get actionBar(): ActionBar { return this._actionBar; } + set actionBar(value: ActionBar) { if (value !== this._actionBar) { this._actionBar = value; @@ -279,4 +298,14 @@ export class ActionItem extends bindable.Bindable implements dts.ActionItem { public ios: dts.IOSActionItemSettings; public android: dts.AndroidActionItemSettings; -} \ No newline at end of file + private static onItemChanged(data: dependencyObservable.PropertyChangeData) { + var menuItem = data.object; + if (menuItem.actionBar) { + menuItem.actionBar.update(); + } + } +} + +export function isVisible(item: dts.ActionItem) { + return item.visibility === enums.Visibility.visible; +} diff --git a/ui/action-bar/action-bar.android.ts b/ui/action-bar/action-bar.android.ts index f777f2248..13bc0a141 100644 --- a/ui/action-bar/action-bar.android.ts +++ b/ui/action-bar/action-bar.android.ts @@ -142,8 +142,7 @@ export class ActionBar extends common.ActionBar { public _updateNavigationButton() { var navButton = this.navigationButton; - if (navButton) { - + if (navButton && common.isVisible(navButton)) { if (navButton.android.systemIcon) { // Try to look in the system resources. let systemResourceId = getSystemResourceId(navButton.android.systemIcon); @@ -208,7 +207,7 @@ export class ActionBar extends common.ActionBar { public _addActionItems() { var menu = this._toolbar.getMenu(); - var items = this.actionItems.getItems(); + var items = this.actionItems.getVisibleItems(); menu.clear(); for (var i = 0; i < items.length; i++) { diff --git a/ui/action-bar/action-bar.d.ts b/ui/action-bar/action-bar.d.ts index 71b1068f4..88cc7ab2b 100644 --- a/ui/action-bar/action-bar.d.ts +++ b/ui/action-bar/action-bar.d.ts @@ -103,6 +103,11 @@ declare module "ui/action-bar" { */ public static iconProperty: dependencyObservable.Property; + /** + * Represents the observable property backing the visibility property. + */ + public static visibilityProperty: dependencyObservable.Property; + /** * Gets or sets the text of the action item. */ @@ -112,6 +117,11 @@ declare module "ui/action-bar" { * Gets or sets the icon of the action item. */ icon: string; + + /** + * Gets or sets the visibility of the action item. + */ + visibility: string; /** * Gets the action bar that contains the action item. diff --git a/ui/action-bar/action-bar.ios.ts b/ui/action-bar/action-bar.ios.ts index 8e93ae335..bb93edf86 100644 --- a/ui/action-bar/action-bar.ios.ts +++ b/ui/action-bar/action-bar.ios.ts @@ -35,8 +35,8 @@ export class ActionBar extends common.ActionBar { var viewController = (this.page.ios); var navigationItem: UINavigationItem = viewController.navigationItem; - var navController = frameModule.topmost().ios.controller; - var navigationBar = navController.navigationBar; + var navController = frameModule.topmost().ios.controller; + var navigationBar = navController.navigationBar; var previousController: UIViewController; // Set Title @@ -66,7 +66,7 @@ export class ActionBar extends common.ActionBar { // Set back button image var img: imageSource.ImageSource; - if (this.navigationButton && this.navigationButton.icon) { + if (this.navigationButton && common.isVisible(this.navigationButton) && this.navigationButton.icon) { img = imageSource.fromFileOrResource(this.navigationButton.icon); } @@ -83,6 +83,11 @@ export class ActionBar extends common.ActionBar { navigationBar.backIndicatorTransitionMaskImage = null; } + // Set back button visibility + if (this.navigationButton) { + navigationItem.setHidesBackButtonAnimated(!common.isVisible(this.navigationButton), true); + } + // Populate action items this.populateMenuItems(navigationItem); @@ -91,7 +96,7 @@ export class ActionBar extends common.ActionBar { } private populateMenuItems(navigationItem: UINavigationItem) { - var items = this.actionItems.getItems(); + var items = this.actionItems.getVisibleItems(); var leftBarItems = []; var rightBarItems = [];