From b58e0b08a3babfa273185893222f0450c8c538a3 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Sun, 18 Sep 2016 05:31:16 +0300 Subject: [PATCH] refactoring --- tns-core-modules/color/color-common.ts | 3 + tns-core-modules/color/color.android.ts | 2 +- tns-core-modules/color/color.d.ts | 2 +- tns-core-modules/color/color.ios.ts | 2 +- tns-core-modules/declarations.d.ts | 6 + .../org.nativescript.widgets.d.ts | 270 ++ .../text/formatted-string.android.ts | 2 +- tns-core-modules/text/formatted-string.d.ts | 1 + .../ui/action-bar/action-bar-common.ts | 247 +- .../ui/action-bar/action-bar.android.ts | 267 +- .../ui/action-bar/action-bar.d.ts | 102 +- .../ui/action-bar/action-bar.ios.ts | 256 +- .../activity-indicator-common.ts | 22 +- .../activity-indicator.android.ts | 88 +- .../activity-indicator.d.ts | 14 +- .../activity-indicator.ios.ts | 82 +- .../ui/animation/animation-common.ts | 103 +- .../ui/animation/animation.android.ts | 284 +- tns-core-modules/ui/animation/animation.d.ts | 18 +- .../ui/animation/animation.ios.ts | 347 +-- .../ui/animation/keyframe-animation.d.ts | 6 +- .../ui/animation/keyframe-animation.ts | 88 +- tns-core-modules/ui/border/border.d.ts | 2 +- tns-core-modules/ui/border/border.ts | 40 +- tns-core-modules/ui/button/button-common.ts | 130 +- tns-core-modules/ui/button/button.android.ts | 162 +- tns-core-modules/ui/button/button.d.ts | 47 +- tns-core-modules/ui/core/bindable.d.ts | 21 +- tns-core-modules/ui/core/bindable.ts | 10 +- tns-core-modules/ui/core/properties.d.ts | 40 + tns-core-modules/ui/core/properties.ts | 585 ++++ tns-core-modules/ui/core/proxy.d.ts | 12 +- tns-core-modules/ui/core/proxy.ts | 106 +- tns-core-modules/ui/core/view-base.ts | 96 + tns-core-modules/ui/core/view-common.ts | 556 ++-- tns-core-modules/ui/core/view.android.ts | 1166 +++++--- tns-core-modules/ui/core/view.d.ts | 98 +- tns-core-modules/ui/definitions.d.ts | 68 + tns-core-modules/ui/label/label-common.ts | 1 - tns-core-modules/ui/label/label.android.ts | 18 + .../ui/layouts/layout-base-common.ts | 4 +- .../ui/styling/css-animation-parser.ts | 298 +- tns-core-modules/ui/styling/package.json | 4 +- .../ui/styling/style-property.d.ts | 42 +- tns-core-modules/ui/styling/style-property.ts | 156 +- tns-core-modules/ui/styling/style-scope.ts | 137 +- tns-core-modules/ui/styling/style.d.ts | 283 +- tns-core-modules/ui/styling/style.ts | 2475 ++++++----------- tns-core-modules/ui/styling/styling.d.ts | 606 ++-- tns-core-modules/ui/styling/styling.ts | 52 +- .../ui/text-base/text-base-common.ts | 149 +- .../ui/text-base/text-base-styler.android.ts | 292 +- .../ui/text-base/text-base.android.ts | 101 +- tns-core-modules/ui/text-base/text-base.d.ts | 32 +- .../ui/text-base/text-base.ios.ts | 40 +- 55 files changed, 5228 insertions(+), 4813 deletions(-) create mode 100644 tns-core-modules/org.nativescript.widgets.d.ts create mode 100644 tns-core-modules/ui/core/properties.d.ts create mode 100644 tns-core-modules/ui/core/properties.ts create mode 100644 tns-core-modules/ui/core/view-base.ts create mode 100644 tns-core-modules/ui/definitions.d.ts diff --git a/tns-core-modules/color/color-common.ts b/tns-core-modules/color/color-common.ts index 68a17c402..b601d99a3 100644 --- a/tns-core-modules/color/color-common.ts +++ b/tns-core-modules/color/color-common.ts @@ -14,6 +14,9 @@ export class Color implements definition.Color { private _argb: number; private _name: string; + constructor(color: number); + constructor(color: string); + constructor(a: number, r: number, g: number, b: number); constructor() { if (arguments.length === 1) { var arg = arguments[0]; diff --git a/tns-core-modules/color/color.android.ts b/tns-core-modules/color/color.android.ts index 3c35298ea..ac635303f 100644 --- a/tns-core-modules/color/color.android.ts +++ b/tns-core-modules/color/color.android.ts @@ -8,4 +8,4 @@ export class Color extends common.Color { public _argbFromString(hex: string): number { return android.graphics.Color.parseColor(hex); } -} +} \ No newline at end of file diff --git a/tns-core-modules/color/color.d.ts b/tns-core-modules/color/color.d.ts index e227d87cb..3d4fbae01 100644 --- a/tns-core-modules/color/color.d.ts +++ b/tns-core-modules/color/color.d.ts @@ -75,4 +75,4 @@ declare module "color" { */ public static isValid(value: any): boolean; } -} +} \ No newline at end of file diff --git a/tns-core-modules/color/color.ios.ts b/tns-core-modules/color/color.ios.ts index 20779f16c..4941ba25c 100644 --- a/tns-core-modules/color/color.ios.ts +++ b/tns-core-modules/color/color.ios.ts @@ -26,4 +26,4 @@ export class Color extends common.Color { return intVal; } -} +} \ No newline at end of file diff --git a/tns-core-modules/declarations.d.ts b/tns-core-modules/declarations.d.ts index 506f356cc..75189006d 100644 --- a/tns-core-modules/declarations.d.ts +++ b/tns-core-modules/declarations.d.ts @@ -105,6 +105,12 @@ declare var require: NativeScriptRequire; declare function Deprecated(target: Object, key?: string | symbol, value?: any): void; declare function Experimental(target: Object, key?: string | symbol, value?: any): void; +/** + * Decorates class that implements native Java interfaces. + * @param interfaces Implemented interfaces. + */ +declare function Interfaces(...interfaces): ClassDecorator; + /** * Decorates class that extends native Java class * @param nativeClassName The name of the newly generated class. Must be unique in the application. diff --git a/tns-core-modules/org.nativescript.widgets.d.ts b/tns-core-modules/org.nativescript.widgets.d.ts new file mode 100644 index 000000000..01854a137 --- /dev/null +++ b/tns-core-modules/org.nativescript.widgets.d.ts @@ -0,0 +1,270 @@ +declare module org { + module nativescript { + module widgets { + export class BorderDrawable extends android.graphics.drawable.ColorDrawable { + constructor(density: number); + public refresh( + borderWidth: number, + borderColor: number, + borderRadius: number, + clipPath: string, + backgroundColor: number, + backgroundImage: android.graphics.Bitmap, + backgroundRepeat: string, + backgroundPosition: string, + backgroundPositionParsedCSSValues: native.Array, + backgroundSize: string, + backgroundSizeParsedCSSValues: native.Array + ); + public getBorderWidth(): number; + public getBorderColor(): number; + public getBorderRadius(): number; + public getClipPath(): string; + public getBackgroundColor(): number; + public getBackgroundImage(): android.graphics.Bitmap; + public getBackgroundRepeat(): string; + public getBackgroundPosition(): string; + public getBackgroundSize(): string; + } + + export class CSSValue { + constructor(type: string, str: string, unit: string, value: number); + public getType(): string; + public getString(): string; + public getUnit(): string; + public getValue(): number; + } + + export class CommonLayoutParams extends android.widget.FrameLayout.LayoutParams { + constructor(); + + public widthPercent: number; + public heightPercent: number; + + public topMarginPercent: number; + public leftMarginPercent: number; + public bottomMarginPercent: number; + public rightMarginPercent: number; + + public left: number; + public top: number; + + public dock: Dock; + + public row: number; + public column: number; + + public rowSpan: number; + public columnSpan: number; + } + + export enum Stretch { + none, + aspectFill, + aspectFit, + fill + } + + export enum Dock { + left, + top, + right, + bottom + } + + export enum GridUnitType { + auto, + pixel, + star + } + + export enum Orientation { + horizontal, + vertical + } + + export class OriginPoint { + public static setX(view: android.view.View, value: number); + public static setY(view: android.view.View, value: number); + } + + export class LayoutBase extends android.view.ViewGroup { + constructor(context: android.content.Context); + } + + export class AbsoluteLayout extends LayoutBase { + constructor(context: android.content.Context); + } + + export class DockLayout extends LayoutBase { + constructor(context: android.content.Context); + + public getStretchLastChild(): boolean; + public setStretchLastChild(value: boolean): void; + } + + export class StackLayout extends LayoutBase { + constructor(context: android.content.Context); + + public getOrientation(): Orientation; + public setOrientation(value: Orientation): void; + } + + export class WrapLayout extends LayoutBase { + constructor(context: android.content.Context); + + public getOrientation(): Orientation; + public setOrientation(value: Orientation): void; + + public getItemWidth(): number; + public setItemWidth(value: number): void; + + public getItemHeight(): number; + public setItemHeight(value: number): void; + } + + export class ItemSpec { + constructor(); + constructor(value: number, unitType: GridUnitType); + public getGridUnitType(): GridUnitType; + public getIsAbsolute(): boolean; + public getIsAuto(): boolean; + public getIsStar(): boolean; + public getValue(): number; + public getActualLength(): number; + } + + export class GridLayout extends LayoutBase { + constructor(context: android.content.Context); + + public addRow(itemSpec: ItemSpec): void; + public addColumn(itemSpec: ItemSpec): void; + + public removeRow(itemSpec: ItemSpec): void; + public removeColumn(itemSpec: ItemSpec): void; + + public removeRowAt(index: number): void; + public removeColumnAt(index: number): void; + + public getColumns(): Array; + public getRows(): Array; + } + + export class ContentLayout extends LayoutBase { + constructor(context: android.content.Context); + } + + export class VerticalScrollView extends android.widget.ScrollView { + constructor(context: android.content.Context); + public getScrollableLength(): number; + } + + export class HorizontalScrollView extends android.widget.HorizontalScrollView { + constructor(context: android.content.Context); + public getScrollableLength(): number; + } + + export class ImageView extends android.widget.ImageView { + constructor(context: android.content.Context); + getCornerRadius(): number; + setCornerRadius(radius: number): void; + + getBorderWidth(): number; + setBorderWidth(width: number): void; + } + + export class TabLayout extends android.widget.HorizontalScrollView { + constructor(context: android.content.Context); + constructor(context: android.content.Context, attrs: android.util.IAttributeSet); + constructor(context: android.content.Context, attrs: android.util.IAttributeSet, defStyle: number); + + setSelectedIndicatorColors(color: Array): void; + + setItems(items: Array, viewPager: android.support.v4.view.ViewPager): void; + updateItemAt(position: number, itemSpec: TabItemSpec): void; + + getTextViewForItemAt(index: number): android.widget.TextView; + getViewForItemAt(index: number): android.widget.LinearLayout; + } + + export class TabItemSpec { + title: string; + iconId: number; + iconDrawable: android.graphics.drawable.Drawable; + } + + export class ViewHelper { + public static getMinWidth(view: android.view.View): number; + public static setMinWidth(view: android.view.View, value: number); + + public static getMinHeight(view: android.view.View): number; + public static setMinHeight(view: android.view.View, value: number); + + public static getWidth(view: android.view.View): number; + public static setWidth(view: android.view.View, value: number); + + public static getHeight(view: android.view.View): number; + public static setHeight(view: android.view.View, value: number); + + public static getMargin(view: android.view.View): { left: number, top: number, right: number, bottom: number }; + public static setMargin(view: android.view.View, left: number, top: number, right: number, bottom: number); + + public static getMarginLeft(view: android.view.View): number; + public static setMarginLeft(view: android.view.View, value): number; + + public static getMarginTop(view: android.view.View): number; + public static setMarginTop(view: android.view.View, value: number); + + public static getMarginRight(view: android.view.View): number; + public static setMarginRight(view: android.view.View, value: number); + + public static getMarginBottom(view: android.view.View): number; + public static setMarginBottom(view: android.view.View, value: number); + + public static getHorizontalAlighment(view: android.view.View): string; + public static setHorizontalAlighment(view: android.view.View, value: string); + + public static getVerticalAlignment(view: android.view.View): string; + public static setVerticalAlignment(view: android.view.View, value: string); + + public static getPadding(view: android.view.View): { left: number, top: number, right: number, bottom: number }; + public static setPadding(view: android.view.View, left: number, top: number, right: number, bottom: number); + + public static getPaddingLeft(view: android.view.View): number; + public static setPaddingLeft(view: android.view.View, value: number); + + public static getPaddingTop(view: android.view.View): number; + public static setPaddingTop(view: android.view.View, value: number); + + public static getPaddingRight(view: android.view.View): number; + public static setPaddingRight(view: android.view.View, value: number); + + public static getPaddingBottom(view: android.view.View): number; + public static setPaddingBottom(view: android.view.View, value: number); + + public static getRotate(view: android.view.View): number; + public static setRotate(view: android.view.View, value: number); + + public static getScaleX(view: android.view.View): number; + public static setScaleX(view: android.view.View, value): number; + + public static getScaleY(view: android.view.View): number; + public static setScaleY(view: android.view.View, value): number; + + public static getTranslateX(view: android.view.View): number; + public static setTranslateX(view: android.view.View, value): number; + + public static getTranslateY(view: android.view.View): number; + public static setTranslateY(view: android.view.View, value): number; + + public static getZIndex(view: android.view.View): number; + public static setZIndex(view: android.view.View, value): number; + } + } + } +} + +declare class TNSLabel extends UILabel { + borderThickness: UIEdgeInsets; + padding: UIEdgeInsets; +} \ No newline at end of file diff --git a/tns-core-modules/text/formatted-string.android.ts b/tns-core-modules/text/formatted-string.android.ts index d9d40ff55..254d65904 100644 --- a/tns-core-modules/text/formatted-string.android.ts +++ b/tns-core-modules/text/formatted-string.android.ts @@ -27,4 +27,4 @@ export class FormattedString extends formattedStringCommon.FormattedString { } this._formattedText = ssb; } -} +} \ No newline at end of file diff --git a/tns-core-modules/text/formatted-string.d.ts b/tns-core-modules/text/formatted-string.d.ts index 8c0c323ca..755f1f4ea 100644 --- a/tns-core-modules/text/formatted-string.d.ts +++ b/tns-core-modules/text/formatted-string.d.ts @@ -102,6 +102,7 @@ declare module "text/formatted-string" { //@private createFormattedStringCore(): void; _updateCharactersInRangeReplacementString(rangeLocation: number, rangeLength: number, replacementString: string): void; + _formattedText: any; //@endprivate } } \ No newline at end of file diff --git a/tns-core-modules/ui/action-bar/action-bar-common.ts b/tns-core-modules/ui/action-bar/action-bar-common.ts index 49f2a4524..f23b42d80 100644 --- a/tns-core-modules/ui/action-bar/action-bar-common.ts +++ b/tns-core-modules/ui/action-bar/action-bar-common.ts @@ -1,49 +1,35 @@ -import dts = require("ui/action-bar"); -import pages = require("ui/page"); -import bindable = require("ui/core/bindable"); -import dependencyObservable = require("ui/core/dependency-observable"); -import enums = require("ui/enums"); -import proxy = require("ui/core/proxy"); -import view = require("ui/core/view"); -import * as styleModule from "../styling/style"; +import {ActionBar as ActionBarDefinition, + ActionItems as ActionItemsDefinition, + ActionItem as ActionItemDefinition, + IOSActionItemSettings, AndroidActionItemSettings, AndroidActionBarSettings, + NavigationButton} from "ui/action-bar"; +import {Page} from "ui/page"; +import {Bindable} from "ui/core/bindable"; +import {HorizontalAlignment, VerticalAlignment, Visibility} from "ui/enums"; +import {View} from "ui/core/view"; +import {horizontalAlignmentProperty, verticalAlignmentProperty} from "ui/styling/style"; +import {Property} from "ui/core/properties"; +import {unsetValue} from "ui/core/dependency-observable"; +import {ViewBase} from "ui/core/view-base"; -var ACTION_ITEMS = "actionItems"; - -var style: typeof styleModule; -function ensureStyle() { - if (!style) { - style = require("../styling/style"); - } -} +let ACTION_ITEMS = "actionItems"; export module knownCollections { export var actionItems = "actionItems"; } -function onTitlePropertyChanged(data: dependencyObservable.PropertyChangeData) { - var actionBar = data.object; - actionBar._onTitlePropertyChanged(); -} - -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)); - +export class ActionBarBase extends View implements ActionBarDefinition { private _actionItems: ActionItems; - private _navigationButton: dts.NavigationButton; - private _page: pages.Page; - private _titleView: view.View; + private _navigationButton: NavigationButton; + private _page: Page; + private _titleView: View; - get title(): string { - return this._getValue(ActionBar.titleProperty); - } - set title(value: string) { - this._setValue(ActionBar.titleProperty, value); - } + public title: string; - get navigationButton(): dts.NavigationButton { + get navigationButton(): NavigationButton { return this._navigationButton; } - set navigationButton(value: dts.NavigationButton) { + set navigationButton(value: NavigationButton) { if (this._navigationButton !== value) { if (this._navigationButton) { this._navigationButton.actionBar = undefined; @@ -66,23 +52,22 @@ export class ActionBar extends view.View implements dts.ActionBar { throw new Error("actionItems property is read-only"); } - get titleView(): view.View { + get titleView(): View { return this._titleView; } - set titleView(value: view.View) { + set titleView(value: View) { if (this._titleView !== value) { - ensureStyle(); if (this._titleView) { this._removeView(this._titleView); - this._titleView.style._resetValue(style.horizontalAlignmentProperty, dependencyObservable.ValueSource.Inherited); - this._titleView.style._resetValue(style.verticalAlignmentProperty, dependencyObservable.ValueSource.Inherited); + this._titleView.style[horizontalAlignmentProperty.cssName] = unsetValue; + this._titleView.style[verticalAlignmentProperty.cssName] = unsetValue; } this._titleView = value; if (this._titleView) { - this._titleView.style._setValue(style.horizontalAlignmentProperty, enums.HorizontalAlignment.center, dependencyObservable.ValueSource.Inherited); - this._titleView.style._setValue(style.verticalAlignmentProperty, enums.VerticalAlignment.center, dependencyObservable.ValueSource.Inherited); + this._titleView.style[horizontalAlignmentProperty.cssName] = HorizontalAlignment.center; + this._titleView.style[verticalAlignmentProperty.cssName] = VerticalAlignment.center; this._addView(this._titleView); } @@ -90,20 +75,20 @@ export class ActionBar extends view.View implements dts.ActionBar { } } - get page(): pages.Page { + get page(): Page { return this._page; } - set page(value: pages.Page) { + set page(value: Page) { this._page = value; - - this.unbind("bindingContext"); - this.bind({ - sourceProperty: "bindingContext", - targetProperty: "bindingContext" - }, this._page); + // // TODO: Move this in _eachChildView of Page class. + // this.unbind("bindingContext"); + // this.bind({ + // sourceProperty: "bindingContext", + // targetProperty: "bindingContext" + // }, this._page); } - get android(): dts.AndroidActionBarSettings { + get android(): AndroidActionBarSettings { return undefined; } @@ -140,27 +125,27 @@ export class ActionBar extends view.View implements dts.ActionBar { } public _addChildFromBuilder(name: string, value: any) { - if (value instanceof dts.NavigationButton) { + if (value instanceof NavigationButton) { this.navigationButton = value; } - else if (value instanceof dts.ActionItem) { + else if (value instanceof ActionItemDefinition) { this.actionItems.addItem(value); } - else if (value instanceof view.View) { + else if (value instanceof View) { this.titleView = value; } } - public _onBindingContextChanged(oldValue: any, newValue: any) { - super._onBindingContextChanged(oldValue, newValue); - if (this._navigationButton) { - this._navigationButton.bindingContext = newValue; - } + // public _onBindingContextChanged(oldValue: any, newValue: any) { + // super._onBindingContextChanged(oldValue, newValue); + // if (this._navigationButton) { + // this._navigationButton.bindingContext = newValue; + // } - this._actionItems.getItems().forEach((item, i, arr) => { item.bindingContext = newValue; }); - } + // this._actionItems.getItems().forEach((item, i, arr) => { item.bindingContext = newValue; }); + // } - public _eachChildView(callback: (child: view.View) => boolean) { + public _eachChildView(callback: (child: View) => boolean) { if (this.titleView) { callback(this.titleView); } @@ -186,15 +171,15 @@ export class ActionBar extends view.View implements dts.ActionBar { } } -export class ActionItems implements dts.ActionItems { - private _items: Array = new Array(); - private _actionBar: ActionBar; +export class ActionItems implements ActionItemsDefinition { + private _items = new Array(); + private _actionBar: ActionBarDefinition; - constructor(actionBar: ActionBar) { + constructor(actionBar: ActionBarDefinition) { this._actionBar = actionBar; } - public addItem(item: dts.ActionItem): void { + public addItem(item: ActionItemDefinition): void { if (!item) { throw new Error("Cannot add empty item"); } @@ -204,7 +189,7 @@ export class ActionItems implements dts.ActionItems { this.invalidate(); } - public removeItem(item: dts.ActionItem): void { + public removeItem(item: ActionItemDefinition): void { if (!item) { throw new Error("Cannot remove empty item"); } @@ -219,11 +204,11 @@ export class ActionItems implements dts.ActionItems { this.invalidate(); } - public getItems(): Array { + public getItems(): Array { return this._items.slice(); } - public getVisibleItems(): Array { + public getVisibleItems(): Array { var visibleItems = []; this._items.forEach((item) => { if (isVisible(item)) { @@ -234,7 +219,7 @@ export class ActionItems implements dts.ActionItems { return visibleItems; } - public getItemAt(index: number): dts.ActionItem { + public getItemAt(index: number): ActionItemDefinition { if (index < 0 || index >= this._items.length) { return undefined; } @@ -242,7 +227,7 @@ export class ActionItems implements dts.ActionItems { return this._items[index]; } - public setItems(items: Array) { + public setItems(items: Array) { // Remove all existing items while (this._items.length > 0) { this.removeItem(this._items[this._items.length - 1]); @@ -263,112 +248,96 @@ export class ActionItems implements dts.ActionItems { } } -export class ActionItem extends bindable.Bindable implements dts.ActionItem { +export class ActionItemBase extends ViewBase implements ActionItemDefinition { public static tapEvent = "tap"; - public static textProperty = new dependencyObservable.Property( - "text", "ActionItem", new dependencyObservable.PropertyMetadata("", null, ActionItem.onItemChanged)); + private _actionBar: ActionBarDefinition; + private _actionView: View; - public static iconProperty = new dependencyObservable.Property( - "icon", "ActionItem", new dependencyObservable.PropertyMetadata(null, null, ActionItem.onItemChanged)); + public ios: IOSActionItemSettings; + public android: AndroidActionItemSettings; - public static visibilityProperty = new dependencyObservable.Property( - "visibility", "ActionItem", new dependencyObservable.PropertyMetadata(enums.Visibility.visible, null, ActionItem.onItemChanged)); + public text: string; + public icon: string; + public visibility: string; - private _actionBar: ActionBar; - private _actionView: view.View; - - get actionView(): view.View { + get actionView(): View { return this._actionView; } - set actionView(value: view.View) { + set actionView(value: View) { if (this._actionView !== value) { - ensureStyle(); if (this._actionView && this._actionBar) { this._actionBar._removeView(this._actionView); - this._actionView.style._resetValue(style.horizontalAlignmentProperty, dependencyObservable.ValueSource.Inherited); - this._actionView.style._resetValue(style.verticalAlignmentProperty, dependencyObservable.ValueSource.Inherited); + this._actionView.style[horizontalAlignmentProperty.cssName] = unsetValue; + this._actionView.style[verticalAlignmentProperty.cssName] = unsetValue; } this._actionView = value; - this._addActionViewToActionBar(); - if (this._actionBar) { this._actionBar.update(); } } } - get text(): string { - return this._getValue(ActionItem.textProperty); - } - set text(value: string) { - this._setValue(ActionItem.textProperty, value); - } - - get icon(): string { - return this._getValue(ActionItem.iconProperty); - } - - set icon(value: string) { - this._setValue(ActionItem.iconProperty, value); - } - - get visibility(): string { - return this._getValue(ActionItem.visibilityProperty); - } - - set visibility(value: string) { - this._setValue(ActionItem.visibilityProperty, value); - } - - get actionBar(): ActionBar { + get actionBar(): ActionBarDefinition { return this._actionBar; } - - set actionBar(value: ActionBar) { + set actionBar(value: ActionBarDefinition) { if (value !== this._actionBar) { this._actionBar = value; if (this._actionBar) { - this.bindingContext = this._actionBar.bindingContext; + // ActionBarBase overrides _eachChildView so bindingContext should work without any manual work. + // this.bindingContext = this._actionBar.bindingContext; this._addActionViewToActionBar(); } } } - get page(): pages.Page { + get page(): Page { return this.actionBar ? this.actionBar.page : undefined; } public _raiseTap() { - this._emit(ActionItem.tapEvent); - } - - public ios: dts.IOSActionItemSettings; - - public android: dts.AndroidActionItemSettings; - private static onItemChanged(data: dependencyObservable.PropertyChangeData) { - var menuItem = data.object; - if (menuItem.actionBar) { - menuItem.actionBar.update(); - } - } - - private _addActionViewToActionBar() { - if (this._actionView && !this._actionView._isAddedToNativeVisualTree && this._actionBar) { - ensureStyle(); - this._actionView.style._setValue(style.horizontalAlignmentProperty, enums.HorizontalAlignment.center, dependencyObservable.ValueSource.Inherited); - this._actionView.style._setValue(style.verticalAlignmentProperty, enums.VerticalAlignment.center, dependencyObservable.ValueSource.Inherited); - this._actionBar._addView(this._actionView); - } + this._emit(ActionItemBase.tapEvent); } public _addChildFromBuilder(name: string, value: any) { this.actionView = value; } + + private _addActionViewToActionBar() { + if (this._actionView && !this._actionView._isAddedToNativeVisualTree && this._actionBar) { + this._actionView.style[horizontalAlignmentProperty.cssName] = HorizontalAlignment.center; + this._actionView.style[verticalAlignmentProperty.cssName] = VerticalAlignment.center; + this._actionBar._addView(this._actionView); + } + } } -export function isVisible(item: dts.ActionItem) { - return item.visibility === enums.Visibility.visible; +export function isVisible(item: ActionItemDefinition) { + return item.visibility === Visibility.visible; } + +function onTitlePropertyChanged(actionBar: ActionBarBase, oldValue: string, newValue: string) { + actionBar._onTitlePropertyChanged(); +} + +let titleProperty = new Property({ name: "title", valueChanged: onTitlePropertyChanged }); +titleProperty.register(ActionBarBase); + + +function onItemChanged(item: ActionItemBase, oldValue: string, newValue: string) { + if (item.actionBar) { + item.actionBar.update(); + } +} + +let textProperty = new Property({ name: "text", defaultValue: "", valueChanged: onItemChanged }); +textProperty.register(ActionItemBase); + +let iconProperty = new Property({ name: "icon", valueChanged: onItemChanged }); +iconProperty.register(ActionItemBase); + +let visibilityProperty = new Property({ name: "visibility", defaultValue: Visibility.visible, valueChanged: onItemChanged }); +visibilityProperty.register(ActionItemBase); \ No newline at end of file diff --git a/tns-core-modules/ui/action-bar/action-bar.android.ts b/tns-core-modules/ui/action-bar/action-bar.android.ts index fe5d63943..79f80fbd2 100644 --- a/tns-core-modules/ui/action-bar/action-bar.android.ts +++ b/tns-core-modules/ui/action-bar/action-bar.android.ts @@ -1,61 +1,42 @@ -import common = require("./action-bar-common"); -import types = require("utils/types"); -import enums = require("ui/enums"); -import application = require("application"); -import dts = require("ui/action-bar"); -import view = require("ui/core/view"); -import * as traceModule from "trace"; -import * as utilsModule from "utils/utils"; -import * as imageSourceModule from "image-source"; -import style = require("ui/styling/style"); +import {AndroidActionBarSettings as AndroidActionBarSettingsDefinition, AndroidActionItemSettings} from "ui/action-bar"; +import {ActionItemBase, ActionBarBase, isVisible} from "./action-bar-common"; +import {isDefined, isNullOrUndefined, isString} from "utils/types"; +import {View} from "ui/core/view"; +import {RESOURCE_PREFIX} from "utils/utils"; +import {fromFileOrResource} from "image-source"; +import {AndroidActionItemPosition, AndroidActionBarIconVisibility} from "ui/enums"; +import {colorProperty} from "ui/styling/style"; +import {Color} from "color"; +import * as application from "application"; +import * as trace from "trace"; + +export * from "./action-bar-common"; const R_ID_HOME = 0x0102002c; const ACTION_ITEM_ID_OFFSET = 1000; -global.moduleMerge(common, exports); - -var trace: typeof traceModule; -function ensureTrace() { - if (!trace) { - trace = require("trace"); - } -} - -var utils: typeof utilsModule; -function ensureUtils() { - if (!utils) { - utils = require("utils/utils"); - } -} - -var imageSource: typeof imageSourceModule; -function ensureImageSource() { - if (!imageSource) { - imageSource = require("image-source"); - } -} - -var actionItemIdGenerator = ACTION_ITEM_ID_OFFSET; +let actionItemIdGenerator = ACTION_ITEM_ID_OFFSET; function generateItemId(): number { actionItemIdGenerator++; return actionItemIdGenerator; } -export class ActionItem extends common.ActionItem { - private _androidPosition: dts.AndroidActionItemSettings = { - position: enums.AndroidActionItemPosition.actionBar, +export class ActionItem extends ActionItemBase { + private _androidPosition: AndroidActionItemSettings = { + position: AndroidActionItemPosition.actionBar, systemIcon: undefined }; + private _itemId; constructor() { super(); this._itemId = generateItemId(); } - public get android(): dts.AndroidActionItemSettings { + public get android(): AndroidActionItemSettings { return this._androidPosition; } - public set android(value: dts.AndroidActionItemSettings) { + public set android(value: AndroidActionItemSettings) { throw new Error("ActionItem.android is read-only"); } @@ -64,10 +45,14 @@ export class ActionItem extends common.ActionItem { } } -export class AndroidActionBarSettings implements dts.AndroidActionBarSettings { +export class AndroidActionBarSettings implements AndroidActionBarSettingsDefinition { private _actionBar: ActionBar; private _icon: string; - private _iconVisibility: string = enums.AndroidActionBarIconVisibility.auto; + private _iconVisibility: string = AndroidActionBarIconVisibility.auto; + + constructor(actionBar: ActionBar) { + this._actionBar = actionBar; + } public get icon(): string { return this._icon; @@ -88,32 +73,17 @@ export class AndroidActionBarSettings implements dts.AndroidActionBarSettings { this._actionBar._onIconPropertyChanged(); } } - - constructor(actionBar: ActionBar) { - this._actionBar = actionBar; - } } -export class NavigationButton extends ActionItem { +export class NavigationButton extends ActionItemBase { } -export class ActionBar extends common.ActionBar { +export class ActionBar extends ActionBarBase { private _appResources: android.content.res.Resources; private _android: AndroidActionBarSettings; - private _toolbar: android.support.v7.widget.Toolbar; - get android(): AndroidActionBarSettings { - return this._android; - } - - set android(value: AndroidActionBarSettings) { - throw new Error("ActionBar.android is read-only"); - } - - get _nativeView() { - return this._toolbar; - } + nativeView: android.support.v7.widget.Toolbar; constructor() { super(); @@ -122,12 +92,19 @@ export class ActionBar extends common.ActionBar { this._android = new AndroidActionBarSettings(this); } + get android(): AndroidActionBarSettings { + return this._android; + } + set android(value: AndroidActionBarSettings) { + throw new Error("ActionBar.android is read-only"); + } + public _createUI() { - this._toolbar = new android.support.v7.widget.Toolbar(this._context); + this.nativeView = new android.support.v7.widget.Toolbar(this._context); let ownerRef = new WeakRef(this); - this._toolbar.setOnMenuItemClickListener(new android.support.v7.widget.Toolbar.OnMenuItemClickListener({ + this.nativeView.setOnMenuItemClickListener(new android.support.v7.widget.Toolbar.OnMenuItemClickListener({ onMenuItemClick: function (item: android.view.IMenuItem): boolean { - let ownerValue = ownerRef.get(); + let ownerValue = ownerRef.get(); if (!ownerValue) { return false; } @@ -143,17 +120,18 @@ export class ActionBar extends common.ActionBar { } public update() { - if (!this._toolbar) { + if (!this.nativeView) { return; } if (!this.page.frame || !this.page.frame._getNavBarVisible(this.page)) { - this._toolbar.setVisibility(android.view.View.GONE); + this.nativeView.setVisibility(android.view.View.GONE); // If action bar is hidden - no need to fill it with items. return; } - this._toolbar.setVisibility(android.view.View.VISIBLE); + + this.nativeView.setVisibility(android.view.View.VISIBLE); // Add menu items this._addActionItems(); @@ -176,11 +154,11 @@ export class ActionBar extends common.ActionBar { } // Find item with the right ID; - var menuItem: dts.ActionItem = undefined; - var items = this.actionItems.getItems(); + let menuItem: ActionItem = undefined; + let items = this.actionItems.getItems(); for (let i = 0; i < items.length; i++) { if ((items[i])._getItemId() === itemId) { - menuItem = items[i]; + menuItem = items[i]; break; } } @@ -195,21 +173,21 @@ export class ActionBar extends common.ActionBar { public _updateNavigationButton() { let navButton = this.navigationButton; - if (navButton && common.isVisible(navButton)) { + if (navButton && isVisible(navButton)) { if (navButton.android.systemIcon) { // Try to look in the system resources. let systemResourceId = getSystemResourceId(navButton.android.systemIcon); if (systemResourceId) { - this._toolbar.setNavigationIcon(systemResourceId); + this.nativeView.setNavigationIcon(systemResourceId); } } else if (navButton.icon) { let drawableOrId = getDrawableOrResourceId(navButton.icon, this._appResources); - this._toolbar.setNavigationIcon(drawableOrId); + this.nativeView.setNavigationIcon(drawableOrId); } let navBtn = new WeakRef(navButton); - this._toolbar.setNavigationOnClickListener(new android.view.View.OnClickListener({ + this.nativeView.setNavigationOnClickListener(new android.view.View.OnClickListener({ onClick: function (v) { let owner = navBtn.get(); if (owner) { @@ -219,59 +197,59 @@ export class ActionBar extends common.ActionBar { })); } else { - this._toolbar.setNavigationIcon(null); + this.nativeView.setNavigationIcon(null); } } public _updateIcon() { - var visibility = getIconVisibility(this.android.iconVisibility); + let visibility = getIconVisibility(this.android.iconVisibility); if (visibility) { - var icon = this.android.icon; - if (types.isDefined(icon)) { - var drawableOrId = getDrawableOrResourceId(icon, this._appResources); + let icon = this.android.icon; + if (isDefined(icon)) { + let drawableOrId = getDrawableOrResourceId(icon, this._appResources); if (drawableOrId) { - this._toolbar.setLogo(drawableOrId); + this.nativeView.setLogo(drawableOrId); } } else { - var defaultIcon = application.android.nativeApp.getApplicationInfo().icon; - this._toolbar.setLogo(defaultIcon); + let defaultIcon = application.android.nativeApp.getApplicationInfo().icon; + this.nativeView.setLogo(defaultIcon); } } else { - this._toolbar.setLogo(null); + this.nativeView.setLogo(null); } } public _updateTitleAndTitleView() { if (!this.titleView) { // No title view - show the title - var title = this.title; - if (types.isDefined(title)) { - this._toolbar.setTitle(title); + let title = this.title; + if (isDefined(title)) { + this.nativeView.setTitle(title); } else { - var appContext = application.android.context; - var appInfo = appContext.getApplicationInfo(); - var appLabel = appContext.getPackageManager().getApplicationLabel(appInfo); + let appContext = application.android.context; + let appInfo = appContext.getApplicationInfo(); + let appLabel = appContext.getPackageManager().getApplicationLabel(appInfo); if (appLabel) { - this._toolbar.setTitle(appLabel); + this.nativeView.setTitle(appLabel); } } } } public _addActionItems() { - var menu = this._toolbar.getMenu(); - var items = this.actionItems.getVisibleItems(); + let menu = this.nativeView.getMenu(); + let items = this.actionItems.getVisibleItems(); menu.clear(); - for (var i = 0; i < items.length; i++) { - var item = items[i]; - var menuItem = menu.add(android.view.Menu.NONE, item._getItemId(), android.view.Menu.NONE, item.text + ""); + for (let i = 0; i < items.length; i++) { + let item = items[i]; + let menuItem = menu.add(android.view.Menu.NONE, item._getItemId(), android.view.Menu.NONE, item.text + ""); if (item.actionView && item.actionView.android) { // With custom action view, the menuitem cannot be displayed in a popup menu. - item.android.position = enums.AndroidActionItemPosition.actionBar; + item.android.position = AndroidActionItemPosition.actionBar; menuItem.setActionView(item.actionView.android); ActionBar._setOnClickListener(item); } @@ -283,7 +261,7 @@ export class ActionBar extends common.ActionBar { } } else if (item.icon) { - var drawableOrId = getDrawableOrResourceId(item.icon, this._appResources); + let drawableOrId = getDrawableOrResourceId(item.icon, this._appResources); if (drawableOrId) { menuItem.setIcon(drawableOrId); } @@ -292,7 +270,7 @@ export class ActionBar extends common.ActionBar { } } - var showAsAction = getShowAsAction(item); + let showAsAction = getShowAsAction(item); menuItem.setShowAsAction(showAsAction); } } @@ -306,32 +284,31 @@ export class ActionBar extends common.ActionBar { } public _onTitlePropertyChanged() { - if (this._toolbar) { + if (this.nativeView) { this._updateTitleAndTitleView(); } } public _onIconPropertyChanged() { - if (this._toolbar) { + if (this.nativeView) { this._updateIcon(); } } public _clearAndroidReference() { // don't clear _android field! - this._toolbar = undefined; + this.nativeView = undefined; } - public _addViewToNativeVisualTree(child: view.View, atIndex?: number): boolean { + public _addViewToNativeVisualTree(child: View, atIndex?: number): boolean { super._addViewToNativeVisualTree(child); - if (this._toolbar && child._nativeView) { - - if (types.isNullOrUndefined(atIndex) || atIndex >= this._nativeView.getChildCount()) { - this._toolbar.addView(child._nativeView); + if (this.nativeView && child._nativeView) { + if (isNullOrUndefined(atIndex) || atIndex >= this._nativeView.getChildCount()) { + this.nativeView.addView(child._nativeView); } else { - this._toolbar.addView(child._nativeView, atIndex); + this.nativeView.addView(child._nativeView, atIndex); } return true; } @@ -339,38 +316,47 @@ export class ActionBar extends common.ActionBar { return false; } - public _removeViewFromNativeVisualTree(child: view.View): void { + public _removeViewFromNativeVisualTree(child: View): void { super._removeViewFromNativeVisualTree(child); - if (this._toolbar && child._nativeView) { - this._toolbar.removeView(child._nativeView); - - ensureTrace(); - + if (this.nativeView && child._nativeView) { + this.nativeView.removeView(child._nativeView); trace.notifyEvent(child, "childInLayoutRemovedFromNativeVisualTree"); } } + + + get [colorProperty.native](): Color { + if (!defaultTitleTextColor) { + let textView = new android.widget.TextView(this._context); + let color = textView.getTextColors().getDefaultColor(); + defaultTitleTextColor = new Color(color); + } + + return defaultTitleTextColor; + } + set [colorProperty.native](value: Color) { + this.nativeView.setTitleTextColor(value.android); + } } +let defaultTitleTextColor: Color; + function getDrawableOrResourceId(icon: string, resources: android.content.res.Resources): any { - if (!types.isString(icon)) { + if (!isString(icon)) { return undefined; } - ensureUtils(); - - if (icon.indexOf(utils.RESOURCE_PREFIX) === 0) { - var resourceId: number = resources.getIdentifier(icon.substr(utils.RESOURCE_PREFIX.length), 'drawable', application.android.packageName); + if (icon.indexOf(RESOURCE_PREFIX) === 0) { + let resourceId: number = resources.getIdentifier(icon.substr(RESOURCE_PREFIX.length), 'drawable', application.android.packageName); if (resourceId > 0) { return resourceId; } } else { - var drawable: android.graphics.drawable.BitmapDrawable; + let drawable: android.graphics.drawable.BitmapDrawable; - ensureImageSource(); - - var is = imageSource.fromFileOrResource(icon); + let is = fromFileOrResource(icon); if (is) { drawable = new android.graphics.drawable.BitmapDrawable(is.android); } @@ -381,15 +367,15 @@ function getDrawableOrResourceId(icon: string, resources: android.content.res.Re return undefined; } -function getShowAsAction(menuItem: dts.ActionItem): number { +function getShowAsAction(menuItem: ActionItem): number { switch (menuItem.android.position) { - case enums.AndroidActionItemPosition.actionBarIfRoom: + case AndroidActionItemPosition.actionBarIfRoom: return android.view.MenuItem.SHOW_AS_ACTION_IF_ROOM; - case enums.AndroidActionItemPosition.popup: + case AndroidActionItemPosition.popup: return android.view.MenuItem.SHOW_AS_ACTION_NEVER; - case enums.AndroidActionItemPosition.actionBar: + case AndroidActionItemPosition.actionBar: default: return android.view.MenuItem.SHOW_AS_ACTION_ALWAYS; } @@ -397,11 +383,11 @@ function getShowAsAction(menuItem: dts.ActionItem): number { function getIconVisibility(iconVisibility: string): boolean { switch (iconVisibility) { - case enums.AndroidActionBarIconVisibility.always: + case AndroidActionBarIconVisibility.always: return true; - case enums.AndroidActionBarIconVisibility.auto: - case enums.AndroidActionBarIconVisibility.never: + case AndroidActionBarIconVisibility.auto: + case AndroidActionBarIconVisibility.never: default: return false; } @@ -409,29 +395,4 @@ function getIconVisibility(iconVisibility: string): boolean { function getSystemResourceId(systemIcon: string): number { return android.content.res.Resources.getSystem().getIdentifier(systemIcon, "drawable", "android"); -} - -export class ActionBarStyler implements style.Styler { - // color - private static setColorProperty(v: view.View, newValue: any) { - var toolbar = (v._nativeView); - toolbar.setTitleTextColor(newValue); - - } - - private static resetColorProperty(v: view.View, nativeValue: any) { - // there is no toolbar.getTitleTextColor - so default to black - if (types.isNullOrUndefined(nativeValue)) { - nativeValue = android.graphics.Color.BLACK; - } - (v._nativeView).setTitleTextColor(nativeValue); - } - - public static registerHandlers() { - style.registerHandler(style.colorProperty, new style.StylePropertyChangedHandler( - ActionBarStyler.setColorProperty, - ActionBarStyler.resetColorProperty), "ActionBar"); - } -} - -ActionBarStyler.registerHandlers(); +} \ No newline at end of file diff --git a/tns-core-modules/ui/action-bar/action-bar.d.ts b/tns-core-modules/ui/action-bar/action-bar.d.ts index 3a559f7fb..8a6109d38 100644 --- a/tns-core-modules/ui/action-bar/action-bar.d.ts +++ b/tns-core-modules/ui/action-bar/action-bar.d.ts @@ -2,17 +2,17 @@ * Contains the action bar related classes. */ declare module "ui/action-bar" { - import observable = require("data/observable"); - import view = require("ui/core/view"); - import dependencyObservable = require("ui/core/dependency-observable"); - import bindable = require("ui/core/bindable"); - import pages = require("ui/page"); + import {EventData} from "data/observable"; + import {View, AddArrayFromBuilder, AddChildFromBuilder} from "ui/core/view"; + import {Property} from "ui/core/properties"; + import {Page} from "ui/page"; + import {ViewBase} from "ui/core/view-base"; /** * Provides an abstraction over the ActionBar (android) and NavigationBar (iOS). */ - export class ActionBar extends view.View implements view.AddArrayFromBuilder, view.AddChildFromBuilder { - + export class ActionBar extends View implements AddArrayFromBuilder, AddChildFromBuilder { + /** * Gets or sets the action bar title. */ @@ -21,18 +21,18 @@ declare module "ui/action-bar" { /** * Gets or sets the title view. When set - replaces the title with a custom view. */ - titleView: view.View; - + titleView: View; + /** * Gets or sets the navigation button (a.k.a. the back button). */ navigationButton: NavigationButton; - + /** * Gets the collection of action items. */ actionItems: ActionItems; - + /** * Gets the android specific options of the action bar. */ @@ -41,7 +41,7 @@ declare module "ui/action-bar" { /** * Gets the page that contains the action bar. */ - page: pages.Page; + page: Page; /** * Updates the action bar. @@ -65,18 +65,18 @@ declare module "ui/action-bar" { * @param item - the item to be added */ addItem(item: ActionItem): void; - + /** * Removes an item to the collection. * @param item - The item to be removed. */ removeItem(item: ActionItem): void; - + /** * Gets an array of the current action items in the collection. */ getItems(): Array; - + /** * Gets an item at a specified index. * @param index - The index. @@ -87,47 +87,27 @@ declare module "ui/action-bar" { /** * Represents an action item in the action bar. */ - export class ActionItem extends bindable.Bindable { - /** - * String value used when hooking to tap event. - */ - public static tapEvent: string; - - /** - * Represents the observable property backing the text property. - */ - public static textProperty: dependencyObservable.Property; - - /** - * Represents the observable property backing the icon property. - */ - public static iconProperty: dependencyObservable.Property; - - /** - * Represents the observable property backing the visibility property. - */ - public static visibilityProperty: dependencyObservable.Property; - + export class ActionItem extends ViewBase { /** * Gets or sets the text of the action item. */ text: string; - + /** * Gets or sets the icon of the action item. */ icon: string; - + /** * Gets or sets the custom action view of the action item. */ - actionView: view.View; + actionView: View; /** * Gets or sets the visibility of the action item. */ visibility: string; - + /** * Gets the action bar that contains the action item. */ @@ -136,7 +116,7 @@ declare module "ui/action-bar" { /** * Gets the page that contains the action item. */ - page: pages.Page; + page: Page; /** * A basic method signature to hook an event listener (shortcut alias to the addEventListener method). @@ -144,12 +124,12 @@ declare module "ui/action-bar" { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (data: observable.EventData) => void); + on(eventNames: string, callback: (data: EventData) => void); /** * Raised when a tap event occurs. */ - on(event: "tap", callback: (args: observable.EventData) => void); + on(event: "tap", callback: (args: EventData) => void); //@private _raiseTap(): void; @@ -159,13 +139,13 @@ declare module "ui/action-bar" { * Gets the iOS specific options of the action item. */ ios: IOSActionItemSettings; - + /** * Gets the Android specific options of the action item. */ android: AndroidActionItemSettings; } - + /** * Represents Android specific options of the action item. */ @@ -178,7 +158,7 @@ declare module "ui/action-bar" { * Note: Property not applicable to NavigationButton */ position: string; - + /** * Gets or sets the name of the system drawable resource to be displayed. * Use this property instead of ActionItem.icon if you want to diplsay a built-in Android system icon. @@ -187,7 +167,7 @@ declare module "ui/action-bar" { */ systemIcon: string; } - + /** * Represents iOS specific options of the action item. */ @@ -238,12 +218,12 @@ declare module "ui/action-bar" { * Represents Android specific options of the action bar. */ export interface AndroidActionBarSettings { - + /** * Gets or sets the action bar icon. */ icon: string; - + /** * Gets or sets the visibility of the action bar icon. * The icon is visible by default in pre-lollipop (API level < 20) versions of android and is hidden in lollipop (API level >= 20) @@ -262,8 +242,28 @@ declare module "ui/action-bar" { } - //@private + /** + * String value used when hooking to tap event. + */ + let tapEvent: string; + + /** + * Represents the observable property backing the text property. + */ + let textProperty: Property; + + /** + * Represents the observable property backing the icon property. + */ + let iconProperty: Property; + + /** + * Represents the observable property backing the visibility property. + */ + let visibilityProperty: Property; + + /** @internal */ export function _setNavBarColor(navBar: any /* UINavigationBar */, color: any /* UIColor */); + /** @internal */ export function _setNavBarBackgroundColor(navBar: any /* UINavigationBar */, color: any /* UIColor */); - //@endprivate } diff --git a/tns-core-modules/ui/action-bar/action-bar.ios.ts b/tns-core-modules/ui/action-bar/action-bar.ios.ts index cd425fab3..91a95831f 100644 --- a/tns-core-modules/ui/action-bar/action-bar.ios.ts +++ b/tns-core-modules/ui/action-bar/action-bar.ios.ts @@ -1,25 +1,48 @@ -import common = require("./action-bar-common"); -import dts = require("ui/action-bar"); -import imageSource = require("image-source"); -import frameModule = require("ui/frame"); -import enums = require("ui/enums"); -import view = require("ui/core/view"); +import {IOSActionItemSettings, ActionItem as ActionItemDefinition} from "ui/action-bar"; +import {ActionItemBase, ActionBarBase, isVisible} from "./action-bar-common"; import utils = require("utils/utils"); -import types = require("utils/types"); -import style = require("ui/styling/style"); -import frame = require("ui/frame"); +import {isNumber} from "utils/types"; +import {Frame, topmost as topmostFrame} from "ui/frame"; +import {View} from "ui/core/view"; +import {ImageSource, fromFileOrResource} from "image-source"; +import {IOSActionItemPosition} from "ui/enums"; +import {colorProperty, backgroundColorProperty, backgroundInternalProperty} from "ui/styling/style"; +import {Color} from "color"; +import {Background} from "ui/styling/background"; -global.moduleMerge(common, exports); +export * from "./action-bar-common"; -export class ActionItem extends common.ActionItem { - private _ios: dts.IOSActionItemSettings = { - position: enums.IOSActionItemPosition.left, +class TapBarItemHandlerImpl extends NSObject { + private _owner: WeakRef; + + public static initWithOwner(owner: WeakRef): TapBarItemHandlerImpl { + let handler = TapBarItemHandlerImpl.new(); + handler._owner = owner; + return handler; + } + + public tap(args) { + let owner = this._owner.get(); + if (owner) { + owner._raiseTap(); + } + } + + public static ObjCExposedMethods = { + "tap": { returns: interop.types.void, params: [interop.types.id] } + }; +} + +export class ActionItem extends ActionItemBase { + private _ios: IOSActionItemSettings = { + position: IOSActionItemPosition.left, systemIcon: undefined }; - public get ios(): dts.IOSActionItemSettings { + + public get ios(): IOSActionItemSettings { return this._ios; } - public set ios(value: dts.IOSActionItemSettings) { + public set ios(value: IOSActionItemSettings) { throw new Error("ActionItem.android is read-only"); } } @@ -28,32 +51,34 @@ export class NavigationButton extends ActionItem { } -export class ActionBar extends common.ActionBar { +export class ActionBar extends ActionBarBase { - get ios(): UIView { + get ios(): UIView { + let page = this.page; + if (!page || !page.parent) { + return; + } - if (!(this.page && this.page.parent)) { + let viewController = (page.ios); + if (viewController.navigationController !== null) { + return viewController.navigationController.navigationBar; + } + + return null; + } + + public update() { + let page = this.page; + // Page should be attached to frame to update the action bar. + if (!page || !page.parent) { return; } let viewController = (this.page.ios); - if (viewController.navigationController !== null) { - return viewController.navigationController.navigationBar; - } - return null; - } - - public update() { - // Page should be attached to frame to update the action bar. - if (!(this.page && this.page.parent)) { - return; - } - - var viewController = (this.page.ios); - var navigationItem: UINavigationItem = viewController.navigationItem; - var navController = frameModule.topmost().ios.controller; - var navigationBar = navController ? navController.navigationBar : null; - var previousController: UIViewController; + let navigationItem: UINavigationItem = viewController.navigationItem; + let navController = page.frame.ios.controller; + let navigationBar = navController ? navController.navigationBar : null; + let previousController: UIViewController; // Set Title navigationItem.title = this.title; @@ -63,7 +88,7 @@ export class ActionBar extends common.ActionBar { } // Find previous ViewController in the navigation stack - var indexOfViewController = navController.viewControllers.indexOfObject(viewController); + let indexOfViewController = navController.viewControllers.indexOfObject(viewController); if (indexOfViewController < navController.viewControllers.count && indexOfViewController > 0) { previousController = navController.viewControllers[indexOfViewController - 1]; } @@ -71,8 +96,8 @@ export class ActionBar extends common.ActionBar { // Set back button text if (previousController) { if (this.navigationButton) { - var tapHandler = TapBarItemHandlerImpl.initWithOwner(new WeakRef(this.navigationButton)); - var barButtonItem = UIBarButtonItem.alloc().initWithTitleStyleTargetAction(this.navigationButton.text + "", UIBarButtonItemStyle.Plain, tapHandler, "tap"); + let tapHandler = TapBarItemHandlerImpl.initWithOwner(new WeakRef(this.navigationButton)); + let barButtonItem = UIBarButtonItem.alloc().initWithTitleStyleTargetAction(this.navigationButton.text + "", UIBarButtonItemStyle.UIBarButtonItemStylePlain, tapHandler, "tap"); previousController.navigationItem.backBarButtonItem = barButtonItem; } else { @@ -81,16 +106,16 @@ export class ActionBar extends common.ActionBar { } // Set back button image - var img: imageSource.ImageSource; - if (this.navigationButton && common.isVisible(this.navigationButton) && this.navigationButton.icon) { - img = imageSource.fromFileOrResource(this.navigationButton.icon); + let img: ImageSource; + if (this.navigationButton && isVisible(this.navigationButton) && this.navigationButton.icon) { + img = fromFileOrResource(this.navigationButton.icon); } // TODO: This could cause issue when canceling BackEdge gesture - we will change the backIndicator to // show the one from the old page but the new page will still be visible (because we canceled EdgeBackSwipe gesutre) // Consider moving this to new method and call it from - navigationControllerDidShowViewControllerAnimated. if (img && img.ios) { - var image = img.ios.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal) + let image = img.ios.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal); navigationBar.backIndicatorImage = image; navigationBar.backIndicatorTransitionMaskImage = image; } @@ -101,7 +126,7 @@ export class ActionBar extends common.ActionBar { // Set back button visibility if (this.navigationButton) { - navigationItem.setHidesBackButtonAnimated(!common.isVisible(this.navigationButton), true); + navigationItem.setHidesBackButtonAnimated(!isVisible(this.navigationButton), true); } // Populate action items @@ -117,13 +142,14 @@ export class ActionBar extends common.ActionBar { let rightBarItems = []; for (let i = 0; i < items.length; i++) { let barButtonItem = this.createBarButtonItem(items[i]); - if (items[i].ios.position === enums.IOSActionItemPosition.left) { + if (items[i].ios.position === IOSActionItemPosition.left) { leftBarItems.push(barButtonItem); } else { rightBarItems.splice(0, 0, barButtonItem); } } + navigationItem.setLeftBarButtonItemsAnimated(leftBarItems, false); navigationItem.setRightBarButtonItemsAnimated(rightBarItems, false); if (leftBarItems.length > 0) { @@ -131,23 +157,22 @@ export class ActionBar extends common.ActionBar { } } - private createBarButtonItem(item: dts.ActionItem): UIBarButtonItem { - var tapHandler = TapBarItemHandlerImpl.initWithOwner(new WeakRef(item)); + private createBarButtonItem(item: ActionItemDefinition): UIBarButtonItem { + let tapHandler = TapBarItemHandlerImpl.initWithOwner(new WeakRef(item)); // associate handler with menuItem or it will get collected by JSC. (item).handler = tapHandler; - var barButtonItem: UIBarButtonItem; - + let barButtonItem: UIBarButtonItem; if (item.actionView && item.actionView.ios) { - var recognizer = UITapGestureRecognizer.alloc().initWithTargetAction(tapHandler, "tap"); + let recognizer = UITapGestureRecognizer.alloc().initWithTargetAction(tapHandler, "tap"); item.actionView.ios.addGestureRecognizer(recognizer); barButtonItem = UIBarButtonItem.alloc().initWithCustomView(item.actionView.ios); } - else if (types.isNumber(item.ios.systemIcon)) { + else if (isNumber(item.ios.systemIcon)) { barButtonItem = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(item.ios.systemIcon, tapHandler, "tap"); } else if (item.icon) { - var img = imageSource.fromFileOrResource(item.icon); + let img = fromFileOrResource(item.icon); if (img && img.ios) { barButtonItem = UIBarButtonItem.alloc().initWithImageStyleTargetAction(img.ios, UIBarButtonItemStyle.Plain, tapHandler, "tap"); } @@ -169,7 +194,7 @@ export class ActionBar extends common.ActionBar { } private updateColors(navBar: UINavigationBar) { - var color = this.color; + let color = this.color; if (color) { navBar.titleTextAttributes = { [NSForegroundColorAttributeName]: color.ios }; navBar.tintColor = color.ios; @@ -179,26 +204,26 @@ export class ActionBar extends common.ActionBar { navBar.tintColor = null; } - var bgColor = this.backgroundColor; + let bgColor = this.backgroundColor; navBar.barTintColor = bgColor ? bgColor.ios : null; } public _onTitlePropertyChanged() { - if (!this.page) { + let page = this.page; + if (!page) { return; } - if (this.page.frame) { - this.page.frame._updateActionBar(); + if (page.frame) { + page.frame._updateActionBar(); } - var navigationItem: UINavigationItem = (this.page.ios).navigationItem; + let navigationItem: UINavigationItem = (page.ios).navigationItem; navigationItem.title = this.title; } private _navigationBarHeight: number = 0; public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number) { - let width = utils.layout.getMeasureSpecSize(widthMeasureSpec); let widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec); @@ -208,7 +233,7 @@ export class ActionBar extends common.ActionBar { let navBarWidth = 0; let navBarHeight = 0; - let frame = this.page.frame; + let frame = this.page.frame; if (frame) { let navBar: UIView = frame.ios.controller.navigationBar; if (!navBar.hidden) { @@ -222,14 +247,14 @@ export class ActionBar extends common.ActionBar { this._navigationBarHeight = navBarHeight; if (this.titleView) { - view.View.measureChild(this, this.titleView, + View.measureChild(this, this.titleView, utils.layout.makeMeasureSpec(width, utils.layout.AT_MOST), utils.layout.makeMeasureSpec(navBarHeight, utils.layout.AT_MOST)); } this.actionItems.getItems().forEach((actionItem) => { if (actionItem.actionView) { - view.View.measureChild(this, actionItem.actionView, + View.measureChild(this, actionItem.actionView, utils.layout.makeMeasureSpec(width, utils.layout.AT_MOST), utils.layout.makeMeasureSpec(navBarHeight, utils.layout.AT_MOST)); } @@ -240,12 +265,12 @@ export class ActionBar extends common.ActionBar { } public onLayout(left: number, top: number, right: number, bottom: number) { - view.View.layoutChild(this, this.titleView, 0, 0, right - left, this._navigationBarHeight); + View.layoutChild(this, this.titleView, 0, 0, right - left, this._navigationBarHeight); this.actionItems.getItems().forEach((actionItem) => { if (actionItem.actionView && actionItem.actionView.ios) { let measuredWidth = actionItem.actionView.getMeasuredWidth(); let measuredHeight = actionItem.actionView.getMeasuredHeight(); - view.View.layoutChild(this, actionItem.actionView, 0, 0, measuredWidth, measuredHeight); + View.layoutChild(this, actionItem.actionView, 0, 0, measuredWidth, measuredHeight); } }); @@ -260,81 +285,48 @@ export class ActionBar extends common.ActionBar { return; } - public _shouldApplyStyleHandlers() { - var topFrame = frameModule.topmost(); - return !!topFrame; - } -} + // public _shouldApplyStyleHandlers() { + // let topFrame = frameModule.topmost(); + // return !!topFrame; + // } -class TapBarItemHandlerImpl extends NSObject { - private _owner: WeakRef; + private get navBar(): UINavigationBar { + let page = this.page; + // Page should be attached to frame to update the action bar. + if (!page || !page.frame) { + return; + } - public static initWithOwner(owner: WeakRef): TapBarItemHandlerImpl { - let handler = TapBarItemHandlerImpl.new(); - handler._owner = owner; - return handler; + return (page.frame.ios.controller).navigationBar; } - public tap(args) { - let owner = this._owner.get(); - if (owner) { - owner._raiseTap(); + get [colorProperty.native](): UIColor { + return null; + } + set [colorProperty.native](color: UIColor) { + let navBar = this.navBar; + navBar.tintColor = color; + navBar.titleTextAttributes = { [NSForegroundColorAttributeName]: color }; + } + + get [backgroundColorProperty.native](): UIColor { + let navBar = this.navBar; + if (navBar) { + return navBar.barTintColor; + } + return null; + } + set [backgroundColorProperty.native](value: UIColor) { + let navBar = this.navBar; + if (navBar) { + navBar.barTintColor = value; } } - public static ObjCExposedMethods = { - "tap": { returns: interop.types.void, params: [interop.types.id] } - }; -} - -export class ActionBarStyler implements style.Styler { - // color - private static setColorProperty(v: view.View, newValue: any) { - var topFrame = frame.topmost(); - if (topFrame) { - var navBar = topFrame.ios.controller.navigationBar; - navBar.titleTextAttributes = { [NSForegroundColorAttributeName]: newValue }; - navBar.tintColor = newValue; - } + get [backgroundInternalProperty.native](): UIColor { + return null; } - - private static resetColorProperty(v: view.View, nativeValue: any) { - var topFrame = frame.topmost(); - if (topFrame) { - var navBar = topFrame.ios.controller.navigationBar; - navBar.titleTextAttributes = null; - navBar.tintColor = null; - } + set [backgroundInternalProperty.native](value: UIColor) { + } - - // background-color - private static setBackgroundColorProperty(v: view.View, newValue: any) { - var topFrame = frame.topmost(); - if (topFrame) { - var navBar = topFrame.ios.controller.navigationBar; - navBar.barTintColor = newValue; - } - } - - private static resetBackgroundColorProperty(v: view.View, nativeValue: any) { - var topFrame = frame.topmost(); - if (topFrame) { - var navBar = topFrame.ios.controller.navigationBar; - navBar.barTintColor = null; - } - } - - public static registerHandlers() { - style.registerHandler(style.colorProperty, new style.StylePropertyChangedHandler( - ActionBarStyler.setColorProperty, - ActionBarStyler.resetColorProperty), "ActionBar"); - - style.registerHandler(style.backgroundColorProperty, new style.StylePropertyChangedHandler( - ActionBarStyler.setBackgroundColorProperty, - ActionBarStyler.resetBackgroundColorProperty), "ActionBar"); - - style.registerHandler(style.backgroundInternalProperty, style.ignorePropertyHandler, "ActionBar"); - } -} - -ActionBarStyler.registerHandlers(); +} \ No newline at end of file diff --git a/tns-core-modules/ui/activity-indicator/activity-indicator-common.ts b/tns-core-modules/ui/activity-indicator/activity-indicator-common.ts index 771a3e00d..9c1972393 100644 --- a/tns-core-modules/ui/activity-indicator/activity-indicator-common.ts +++ b/tns-core-modules/ui/activity-indicator/activity-indicator-common.ts @@ -1,18 +1,10 @@ -import definition = require("ui/activity-indicator"); +import {ActivityIndicator as ActivityIndicatorDefinition} from "ui/activity-indicator"; import {View} from "ui/core/view"; -import {Property} from "ui/core/dependency-observable"; -import {PropertyMetadata} from "ui/core/proxy"; +import {Property} from "ui/core/properties"; -let busyProperty = new Property("busy", "ActivityIndicator", new PropertyMetadata(false)); +export class ActivityIndicatorBase extends View implements ActivityIndicatorDefinition { + public busy: boolean; +} -export class ActivityIndicator extends View implements definition.ActivityIndicator { - - public static busyProperty = busyProperty; - - get busy(): boolean { - return this._getValue(ActivityIndicator.busyProperty); - } - set busy(value: boolean) { - this._setValue(ActivityIndicator.busyProperty, value); - } -} \ No newline at end of file +export let busyProperty = new Property({ name: "busy", defaultValue: false }); +busyProperty.register(ActivityIndicatorBase); \ No newline at end of file diff --git a/tns-core-modules/ui/activity-indicator/activity-indicator.android.ts b/tns-core-modules/ui/activity-indicator/activity-indicator.android.ts index 05efb2262..dfbdecba3 100644 --- a/tns-core-modules/ui/activity-indicator/activity-indicator.android.ts +++ b/tns-core-modules/ui/activity-indicator/activity-indicator.android.ts @@ -1,78 +1,46 @@ -import aiCommon = require("./activity-indicator-common"); -import dependencyObservable = require("ui/core/dependency-observable"); -import proxy = require("ui/core/proxy"); -import enums = require("ui/enums"); -import style = require("ui/styling/style"); -import view = require("ui/core/view"); +import {ActivityIndicatorBase, busyProperty} from "./activity-indicator-common"; +import {Visibility} from "ui/enums"; +import {colorProperty, visibilityProperty} from "ui/styling/style"; -function onBusyPropertyChanged(data: dependencyObservable.PropertyChangeData) { - var indicator = data.object; - if (!indicator.android) { - return; - } +export * from "./activity-indicator-common"; - if (indicator.visibility === enums.Visibility.visible) { - indicator.android.setVisibility(data.newValue ? android.view.View.VISIBLE : android.view.View.INVISIBLE); - } -} - -// register the setNativeValue callback -(aiCommon.ActivityIndicator.busyProperty.metadata).onSetNativeValue = onBusyPropertyChanged; - -global.moduleMerge(aiCommon, exports); - -export class ActivityIndicator extends aiCommon.ActivityIndicator { - private _android: android.widget.ProgressBar; +export class ActivityIndicator extends ActivityIndicatorBase { + nativeView: android.widget.ProgressBar; public _createUI() { - this._android = new android.widget.ProgressBar(this._context); - this._android.setVisibility(android.view.View.INVISIBLE); - this._android.setIndeterminate(true); + this.nativeView = new android.widget.ProgressBar(this._context); + this.nativeView.setVisibility(android.view.View.INVISIBLE); + this.nativeView.setIndeterminate(true); } get android(): android.widget.ProgressBar { - return this._android; - } -} - -export class ActivityIndicatorStyler implements style.Styler { - private static setColorProperty(view: view.View, newValue: any) { - var bar = view._nativeView; - bar.getIndeterminateDrawable().setColorFilter(newValue, android.graphics.PorterDuff.Mode.SRC_IN); + return this.nativeView; } - private static resetColorProperty(view: view.View, nativeValue: number) { - var bar = view._nativeView; - bar.getIndeterminateDrawable().clearColorFilter(); + get [busyProperty.native](): boolean { + return this.nativeView.getVisibility() === android.view.View.VISIBLE; + } + set [busyProperty.native](value: boolean) { + this.nativeView.setVisibility(value ? android.view.View.VISIBLE : android.view.View.INVISIBLE); } - //Visibility methods - public static setActivityIndicatorVisibilityProperty(view: view.View, newValue: any) { - ActivityIndicatorStyler.setIndicatorVisibility((view).busy, newValue, view._nativeView); + get [visibilityProperty.native](): number { + return this.nativeView.getVisibility(); + } + set [visibilityProperty.native](value: number) { + this.busy = value === android.view.View.VISIBLE; + this.nativeView.setVisibility(value); } - public static resetActivityIndicatorVisibilityProperty(view: view.View, nativeValue: any) { - ActivityIndicatorStyler.setIndicatorVisibility((view).busy, enums.Visibility.visible, view._nativeView); + get [colorProperty.native](): number { + return -1; } - - public static setIndicatorVisibility(isBusy: boolean, visibility: string, nativeView: android.view.View) { - if (visibility === enums.Visibility.collapsed || visibility === enums.Visibility.collapse) { - nativeView.setVisibility(android.view.View.GONE); + set [colorProperty.native](value: number) { + if (value < 0) { + this.nativeView.getIndeterminateDrawable().clearColorFilter(); } else { - nativeView.setVisibility(isBusy ? android.view.View.VISIBLE : android.view.View.INVISIBLE); + this.nativeView.getIndeterminateDrawable().setColorFilter(value, android.graphics.PorterDuff.Mode.SRC_IN); } } - - public static registerHandlers() { - style.registerHandler(style.colorProperty, new style.StylePropertyChangedHandler( - ActivityIndicatorStyler.setColorProperty, - ActivityIndicatorStyler.resetColorProperty), "ActivityIndicator"); - - style.registerHandler(style.visibilityProperty, new style.StylePropertyChangedHandler( - ActivityIndicatorStyler.setActivityIndicatorVisibilityProperty, - ActivityIndicatorStyler.resetActivityIndicatorVisibilityProperty), "ActivityIndicator"); - } -} - -ActivityIndicatorStyler.registerHandlers(); +} \ No newline at end of file diff --git a/tns-core-modules/ui/activity-indicator/activity-indicator.d.ts b/tns-core-modules/ui/activity-indicator/activity-indicator.d.ts index 206702a06..489945be0 100644 --- a/tns-core-modules/ui/activity-indicator/activity-indicator.d.ts +++ b/tns-core-modules/ui/activity-indicator/activity-indicator.d.ts @@ -3,17 +3,12 @@ */ declare module "ui/activity-indicator" { import {View} from "ui/core/view"; - import {Property} from "ui/core/dependency-observable"; + import {Property} from "ui/core/properties"; /** * Represents a UI widget which displays a progress indicator hinting the user for some background operation running. */ export class ActivityIndicator extends View { - /** - * Represents the busy property of the ActivityIndicator class. - */ - public static busyProperty: Property; - /** * Gets the native [android widget](http://developer.android.com/reference/android/widget/ProgressBar.html) that represents the user interface for this component. Valid only when running on Android OS. */ @@ -29,4 +24,9 @@ declare module "ui/activity-indicator" { */ busy: boolean; } -} + + /** + * Represents the busy property of the ActivityIndicator class. + */ + let busyProperty: Property; +} \ No newline at end of file diff --git a/tns-core-modules/ui/activity-indicator/activity-indicator.ios.ts b/tns-core-modules/ui/activity-indicator/activity-indicator.ios.ts index fb9070152..c0b76ddcf 100644 --- a/tns-core-modules/ui/activity-indicator/activity-indicator.ios.ts +++ b/tns-core-modules/ui/activity-indicator/activity-indicator.ios.ts @@ -1,67 +1,45 @@ -import aiCommon = require("./activity-indicator-common"); -import dependencyObservable = require("ui/core/dependency-observable"); -import proxy = require("ui/core/proxy"); -import style = require("ui/styling/style"); -import view = require("ui/core/view"); +import {ActivityIndicatorBase, busyProperty} from "./activity-indicator-common"; +import {Visibility} from "ui/enums"; +import {colorProperty, visibilityProperty} from "ui/styling/style"; -function onBusyPropertyChanged(data: dependencyObservable.PropertyChangeData) { - var indicator = data.object; - if (!indicator.ios) { - return; - } - - let activityIndicator = indicator.ios; - if (data.newValue) { - activityIndicator.startAnimating(); - } else { - activityIndicator.stopAnimating(); - } +export * from "./activity-indicator-common"; - if (activityIndicator.hidesWhenStopped) { - indicator.requestLayout(); - } -} - -// register the setNativeValue callback -(aiCommon.ActivityIndicator.busyProperty.metadata).onSetNativeValue = onBusyPropertyChanged; - -global.moduleMerge(aiCommon, exports); - -export class ActivityIndicator extends aiCommon.ActivityIndicator { - private _ios: UIActivityIndicatorView; +export class ActivityIndicator extends ActivityIndicatorBase { + nativeView: UIActivityIndicatorView; constructor() { super(); - this._ios = UIActivityIndicatorView.alloc().initWithActivityIndicatorStyle(UIActivityIndicatorViewStyle.Gray); + this.nativeView = UIActivityIndicatorView.alloc().initWithActivityIndicatorStyle(UIActivityIndicatorViewStyle.UIActivityIndicatorViewStyleGray); + this.nativeView.hidesWhenStopped = true; } - get ios(): UIActivityIndicatorView { - return this._ios; + get [busyProperty.native](): boolean { + return this.nativeView.isAnimating(); } -} + set [busyProperty.native](value: boolean) { + let nativeView = this.nativeView; + if (value) { + nativeView.startAnimating(); + } else { + nativeView.stopAnimating(); + } -export class ActivityIndicatorStyler implements style.Styler { - private static setColorProperty(view: view.View, newValue: any) { - var bar = view.ios; - bar.color = newValue; + if (nativeView.hidesWhenStopped) { + this.requestLayout(); + } } - private static resetColorProperty(view: view.View, nativeValue: any) { - var bar = view.ios; - bar.color = nativeValue; + get [visibilityProperty.native](): string { + return this.nativeView.hidden ? Visibility.collapse : Visibility.visible; + } + set [visibilityProperty.native](value: string) { + this.nativeView.hidden = value !== Visibility.visible; } - private static getNativeColorValue(view: view.View): any { - var bar = view.ios; - return bar.color; + get [colorProperty.native](): UIColor { + return this.nativeView.color; } - - public static registerHandlers() { - style.registerHandler(style.colorProperty, new style.StylePropertyChangedHandler( - ActivityIndicatorStyler.setColorProperty, - ActivityIndicatorStyler.resetColorProperty, - ActivityIndicatorStyler.getNativeColorValue), "ActivityIndicator"); + set [colorProperty.native](value: UIColor) { + this.nativeView.color = value; } -} - -ActivityIndicatorStyler.registerHandlers(); +} \ No newline at end of file diff --git a/tns-core-modules/ui/animation/animation-common.ts b/tns-core-modules/ui/animation/animation-common.ts index 66580257a..60c776c3f 100644 --- a/tns-core-modules/ui/animation/animation-common.ts +++ b/tns-core-modules/ui/animation/animation-common.ts @@ -1,15 +1,12 @@ -import definition = require("ui/animation"); -import viewModule = require("ui/core/view"); -import colorModule = require("color"); -import types = require("utils/types"); -import * as traceModule from "trace"; - -var trace: typeof traceModule; -function ensureTrace() { - if (!trace) { - trace = require("trace"); - } -} +import {CubicBezierAnimationCurve as CubicBezierAnimationCurveDefinition, + AnimationPromise as AnimationPromiseDefinition, + Animation as AnimationBaseDefinition, + AnimationDefinition, + Pair} from "ui/animation"; +import {View} from "ui/core/view"; +import {Color} from "color"; +import {isDefined, isNumber, isString} from "utils/types"; +import * as trace from "trace"; export module Properties { export var opacity = "opacity"; @@ -20,7 +17,7 @@ export module Properties { } export interface PropertyAnimation { - target: viewModule.View; + target: View; property: string; value: any; duration?: number; @@ -29,7 +26,7 @@ export interface PropertyAnimation { curve?: any; } -export class CubicBezierAnimationCurve implements definition.CubicBezierAnimationCurve { +export class CubicBezierAnimationCurve implements CubicBezierAnimationCurveDefinition { public x1: number; public y1: number; @@ -46,19 +43,47 @@ export class CubicBezierAnimationCurve implements definition.CubicBezierAnimatio // This is a BOGUS Class to make TypeScript happy - This is not needed other than to make TS happy. // We didn't want to actually modify Promise; as the cancel() is ONLY valid for animations "Promise" -export class AnimationPromise implements definition.AnimationPromise { +export class AnimationPromise implements AnimationPromiseDefinition { public cancel(): void { /* Do Nothing */ } public then(onFulfilled?: (value?: any) => void, onRejected?: (error?: any) => void): AnimationPromise { return new AnimationPromise(); } public catch(onRejected?: (error?: any) => void): AnimationPromise { return new AnimationPromise(); } } -export class Animation implements definition.Animation { +export abstract class AnimationBase implements AnimationBaseDefinition { public _propertyAnimations: Array; public _playSequentially: boolean; private _isPlaying: boolean; private _resolve; private _reject; + constructor(animationDefinitions: Array, playSequentially?: boolean) { + if (!animationDefinitions || animationDefinitions.length === 0) { + throw new Error("No animation definitions specified"); + } + + if (trace.enabled) { + trace.write("Analyzing " + animationDefinitions.length + " animation definitions...", trace.categories.Animation); + } + this._propertyAnimations = new Array(); + var i = 0; + var length = animationDefinitions.length; + for (; i < length; i++) { + animationDefinitions[i].curve = this._resolveAnimationCurve(animationDefinitions[i].curve); + this._propertyAnimations = this._propertyAnimations.concat(AnimationBase._createPropertyAnimations(animationDefinitions[i])); + } + + if (this._propertyAnimations.length === 0) { + throw new Error("Nothing to animate."); + } + if (trace.enabled) { + trace.write("Created " + this._propertyAnimations.length + " individual property animations.", trace.categories.Animation); + } + + this._playSequentially = playSequentially; + } + + abstract _resolveAnimationCurve(curve: any): any; + public play(): AnimationPromise { if (this.isPlaying) { throw new Error("Animation is already playing."); @@ -107,34 +132,6 @@ export class Animation implements definition.Animation { return this._isPlaying; } - constructor(animationDefinitions: Array, playSequentially?: boolean) { - if (!animationDefinitions || animationDefinitions.length === 0) { - throw new Error("No animation definitions specified"); - } - - ensureTrace(); - - if (trace.enabled) { - trace.write("Analyzing " + animationDefinitions.length + " animation definitions...", trace.categories.Animation); - } - this._propertyAnimations = new Array(); - var i = 0; - var length = animationDefinitions.length; - for (; i < length; i++) { - animationDefinitions[i].curve = definition._resolveAnimationCurve(animationDefinitions[i].curve); - this._propertyAnimations = this._propertyAnimations.concat(Animation._createPropertyAnimations(animationDefinitions[i])); - } - - if (this._propertyAnimations.length === 0) { - throw new Error("Nothing to animate."); - } - if (trace.enabled) { - trace.write("Created " + this._propertyAnimations.length + " individual property animations.", trace.categories.Animation); - } - - this._playSequentially = playSequentially; - } - public _resolveAnimationFinishedPromise() { this._isPlaying = false; this._resolve(); @@ -145,13 +142,13 @@ export class Animation implements definition.Animation { this._reject(new Error("Animation cancelled.")); } - private static _createPropertyAnimations(animationDefinition: definition.AnimationDefinition): Array { + private static _createPropertyAnimations(animationDefinition: AnimationDefinition): Array { if (!animationDefinition.target) { throw new Error("No animation target specified."); } for (let item in animationDefinition) { - if (!types.isDefined(animationDefinition[item])) { + if (!isDefined(animationDefinition[item])) { continue; } @@ -159,14 +156,14 @@ export class Animation implements definition.Animation { item === Properties.rotate || item === "duration" || item === "delay" || - item === "iterations") && !types.isNumber(animationDefinition[item])) { + item === "iterations") && !isNumber(animationDefinition[item])) { throw new Error(`Property ${item} must be valid number. Value: ${animationDefinition[item]}`); } else if ((item === Properties.scale || item === Properties.translate) && - (!types.isNumber((animationDefinition[item]).x) || - !types.isNumber((animationDefinition[item]).y))) { + (!isNumber((animationDefinition[item]).x) || + !isNumber((animationDefinition[item]).y))) { throw new Error(`Property ${item} must be valid Pair. Value: ${animationDefinition[item]}`); - } else if (item === Properties.backgroundColor && !colorModule.Color.isValid(animationDefinition.backgroundColor)) { + } else if (item === Properties.backgroundColor && !Color.isValid(animationDefinition.backgroundColor)) { throw new Error(`Property ${item} must be valid color. Value: ${animationDefinition[item]}`); } } @@ -191,8 +188,8 @@ export class Animation implements definition.Animation { propertyAnimations.push({ target: animationDefinition.target, property: Properties.backgroundColor, - value: types.isString(animationDefinition.backgroundColor) ? - new colorModule.Color(animationDefinition.backgroundColor) : animationDefinition.backgroundColor, + value: isString(animationDefinition.backgroundColor) ? + new Color(animationDefinition.backgroundColor) : animationDefinition.backgroundColor, duration: animationDefinition.duration, delay: animationDefinition.delay, iterations: animationDefinition.iterations, @@ -257,4 +254,4 @@ export class Animation implements definition.Animation { curve: animation.curve }); } -} +} \ No newline at end of file diff --git a/tns-core-modules/ui/animation/animation.android.ts b/tns-core-modules/ui/animation/animation.android.ts index 5f9eb5ec8..96e61e27e 100644 --- a/tns-core-modules/ui/animation/animation.android.ts +++ b/tns-core-modules/ui/animation/animation.android.ts @@ -1,18 +1,18 @@ -import definition = require("ui/animation"); -import common = require("./animation-common"); -import utils = require("utils/utils"); -import color = require("color"); -import trace = require("trace"); -import types = require("utils/types"); -import enums = require("ui/enums"); -import styleModule = require("ui/styling/style"); +import {AnimationDefinition} from "ui/animation"; +import {AnimationBase, Properties, PropertyAnimation, CubicBezierAnimationCurve, AnimationPromise} from "./animation-common"; +import {Color} from "color"; +import {isNullOrUndefined} from "utils/types"; +import {AnimationCurve} from "ui/enums"; import lazy from "utils/lazy"; -import { CacheLayerType } from "utils/utils"; -import dependencyObservable = require("ui/core/dependency-observable"); +import { CacheLayerType, layout } from "utils/utils"; +import {opacityProperty, backgroundColorProperty, rotateProperty, + translateXProperty, translateYProperty, + scaleXProperty, scaleYProperty } from "ui/styling/style"; +import * as trace from "trace"; -global.moduleMerge(common, exports); +export * from "./animation-common"; -interface AnimationDefinitionInternal extends definition.AnimationDefinition { +interface AnimationDefinitionInternal extends AnimationDefinition { valueSource?: number; } @@ -23,15 +23,21 @@ function ensureArgbEvaluator() { } } +let easeIn = lazy(() => new android.view.animation.AccelerateInterpolator(1)); +let easeOut = lazy(() => new android.view.animation.DecelerateInterpolator(1)); +let easeInOut = lazy(() => new android.view.animation.AccelerateDecelerateInterpolator()); +let linear = lazy(() => new android.view.animation.LinearInterpolator()); +let bounce = lazy(() => new android.view.animation.BounceInterpolator()); + let keyPrefix = "ui.animation."; let propertyKeys = {}; -propertyKeys[common.Properties.backgroundColor] = Symbol(keyPrefix + common.Properties.backgroundColor); -propertyKeys[common.Properties.opacity] = Symbol(keyPrefix + common.Properties.opacity); -propertyKeys[common.Properties.rotate] = Symbol(keyPrefix + common.Properties.rotate); -propertyKeys[common.Properties.scale] = Symbol(keyPrefix + common.Properties.scale); -propertyKeys[common.Properties.translate] = Symbol(keyPrefix + common.Properties.translate); +propertyKeys[Properties.backgroundColor] = Symbol(keyPrefix + Properties.backgroundColor); +propertyKeys[Properties.opacity] = Symbol(keyPrefix + Properties.opacity); +propertyKeys[Properties.rotate] = Symbol(keyPrefix + Properties.rotate); +propertyKeys[Properties.scale] = Symbol(keyPrefix + Properties.scale); +propertyKeys[Properties.translate] = Symbol(keyPrefix + Properties.translate); -export class Animation extends common.Animation implements definition.Animation { +export class Animation extends AnimationBase { private _animatorListener: android.animation.Animator.AnimatorListener; private _nativeAnimatorsArray: any; private _animatorSet: android.animation.AnimatorSet; @@ -40,7 +46,41 @@ export class Animation extends common.Animation implements definition.Animation private _propertyResetCallbacks: Array; private _valueSource: number; - public play(): definition.AnimationPromise { + constructor(animationDefinitions: Array, playSequentially?: boolean) { + super(animationDefinitions, playSequentially); + + if (animationDefinitions.length > 0 && animationDefinitions[0].valueSource !== undefined) { + this._valueSource = animationDefinitions[0].valueSource; + } + + let that = new WeakRef(this); + this._animatorListener = new android.animation.Animator.AnimatorListener({ + onAnimationStart: function (animator: android.animation.Animator): void { + if (trace.enabled) { + trace.write("MainAnimatorListener.onAndroidAnimationStart(" + animator + ")", trace.categories.Animation); + } + }, + onAnimationRepeat: function (animator: android.animation.Animator): void { + if (trace.enabled) { + trace.write("MainAnimatorListener.onAnimationRepeat(" + animator + ")", trace.categories.Animation); + } + }, + onAnimationEnd: function (animator: android.animation.Animator): void { + if (trace.enabled) { + trace.write("MainAnimatorListener.onAnimationEnd(" + animator + ")", trace.categories.Animation); + } + that.get()._onAndroidAnimationEnd(); + }, + onAnimationCancel: function (animator: android.animation.Animator): void { + if (trace.enabled) { + trace.write("MainAnimatorListener.onAnimationCancel(" + animator + ")", trace.categories.Animation); + } + that.get()._onAndroidAnimationCancel(); + } + }); + } + + public play(): AnimationPromise { let animationFinishedPromise = super.play(); this._animators = new Array(); @@ -51,7 +91,7 @@ export class Animation extends common.Animation implements definition.Animation this._createAnimators(this._propertyAnimations[i]); } - this._nativeAnimatorsArray = (Array).create(android.animation.Animator, this._animators.length); + this._nativeAnimatorsArray = Array.create(android.animation.Animator, this._animators.length); for (let i = 0, length = this._animators.length; i < length; i++) { this._nativeAnimatorsArray[i] = this._animators[i]; } @@ -85,38 +125,48 @@ export class Animation extends common.Animation implements definition.Animation this._animatorSet.cancel(); } - constructor(animationDefinitions: Array, playSequentially?: boolean) { - super(animationDefinitions, playSequentially); - - if (animationDefinitions.length > 0 && animationDefinitions[0].valueSource !== undefined) { - this._valueSource = animationDefinitions[0].valueSource; + public _resolveAnimationCurve(curve: string | CubicBezierAnimationCurve | android.view.animation.Interpolator): android.view.animation.Interpolator { + switch (curve) { + case AnimationCurve.easeIn: + if (trace.enabled) { + trace.write("Animation curve resolved to android.view.animation.AccelerateInterpolator(1).", trace.categories.Animation); + } + return easeIn(); + case AnimationCurve.easeOut: + if (trace.enabled) { + trace.write("Animation curve resolved to android.view.animation.DecelerateInterpolator(1).", trace.categories.Animation); + } + return easeOut(); + case AnimationCurve.easeInOut: + if (trace.enabled) { + trace.write("Animation curve resolved to android.view.animation.AccelerateDecelerateInterpolator().", trace.categories.Animation); + } + return easeInOut(); + case AnimationCurve.linear: + if (trace.enabled) { + trace.write("Animation curve resolved to android.view.animation.LinearInterpolator().", trace.categories.Animation); + } + return linear(); + case AnimationCurve.spring: + if (trace.enabled) { + trace.write("Animation curve resolved to android.view.animation.BounceInterpolator().", trace.categories.Animation); + } + return bounce(); + case AnimationCurve.ease: + return (android).support.v4.view.animation.PathInterpolatorCompat.create(0.25, 0.1, 0.25, 1.0); + default: + if (trace.enabled) { + trace.write("Animation curve resolved to original: " + curve, trace.categories.Animation); + } + if (curve instanceof CubicBezierAnimationCurve) { + return (android).support.v4.view.animation.PathInterpolatorCompat.create(curve.x1, curve.y1, curve.x2, curve.y2); + } else if (curve instanceof android.view.animation.Interpolator) { + return curve; + } + else { + throw new Error("Invalid android.view.animation.Interpolator."); + } } - - let that = this; - this._animatorListener = new android.animation.Animator.AnimatorListener({ - onAnimationStart: function (animator: android.animation.Animator): void { - if (trace.enabled) { - trace.write("MainAnimatorListener.onAndroidAnimationStart(" + animator +")", trace.categories.Animation); - } - }, - onAnimationRepeat: function (animator: android.animation.Animator): void { - if (trace.enabled) { - trace.write("MainAnimatorListener.onAnimationRepeat(" + animator + ")", trace.categories.Animation); - } - }, - onAnimationEnd: function (animator: android.animation.Animator): void { - if (trace.enabled) { - trace.write("MainAnimatorListener.onAnimationEnd(" + animator + ")", trace.categories.Animation); - } - that._onAndroidAnimationEnd(); - }, - onAnimationCancel: function (animator: android.animation.Animator): void { - if (trace.enabled) { - trace.write("MainAnimatorListener.onAnimationCancel(" + animator + ")", trace.categories.Animation); - } - that._onAndroidAnimationCancel(); - } - }); } private _onAndroidAnimationEnd() { @@ -144,24 +194,24 @@ export class Animation extends common.Animation implements definition.Animation this._rejectAnimationFinishedPromise(); } - private _createAnimators(propertyAnimation: common.PropertyAnimation): void { + private _createAnimators(propertyAnimation: PropertyAnimation): void { if (!propertyAnimation.target._nativeView) { return; } if (trace.enabled) { - trace.write("Creating ObjectAnimator(s) for animation: " + common.Animation._getAnimationInfo(propertyAnimation) + "...", trace.categories.Animation); + trace.write("Creating ObjectAnimator(s) for animation: " + Animation._getAnimationInfo(propertyAnimation) + "...", trace.categories.Animation); } - if (types.isNullOrUndefined(propertyAnimation.target)) { + if (isNullOrUndefined(propertyAnimation.target)) { throw new Error("Animation target cannot be null or undefined!"); } - if (types.isNullOrUndefined(propertyAnimation.property)) { + if (isNullOrUndefined(propertyAnimation.property)) { throw new Error("Animation property cannot be null or undefined!"); } - if (types.isNullOrUndefined(propertyAnimation.value)) { + if (isNullOrUndefined(propertyAnimation.value)) { throw new Error("Animation value cannot be null or undefined!"); } @@ -172,7 +222,7 @@ export class Animation extends common.Animation implements definition.Animation let propertyResetCallbacks = new Array(); let originalValue1; let originalValue2; - let density = utils.layout.getDisplayDensity(); + let density = layout.getDisplayDensity(); let xyObjectAnimators: any; let animatorSet: android.animation.AnimatorSet; @@ -189,55 +239,54 @@ export class Animation extends common.Animation implements definition.Animation } } - let valueSource = this._valueSource !== undefined ? this._valueSource : dependencyObservable.ValueSource.Local; + // let valueSource = this._valueSource !== undefined ? this._valueSource : dependencyObservable.ValueSource.Local; switch (propertyAnimation.property) { - - case common.Properties.opacity: + case Properties.opacity: originalValue1 = nativeView.getAlpha(); - nativeArray = (Array).create("float", 1); + nativeArray = Array.create("float", 1); nativeArray[0] = propertyAnimation.value; propertyUpdateCallbacks.push(checkAnimation(() => { - propertyAnimation.target.style._setValue(styleModule.opacityProperty, propertyAnimation.value, valueSource); + propertyAnimation.target.style[opacityProperty.cssName] = propertyAnimation.value; })); propertyResetCallbacks.push(checkAnimation(() => { - propertyAnimation.target.style._setValue(styleModule.opacityProperty, originalValue1, valueSource); + propertyAnimation.target.style[opacityProperty.cssName] = originalValue1; })); animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "alpha", nativeArray)); break; - case common.Properties.backgroundColor: + case Properties.backgroundColor: ensureArgbEvaluator(); originalValue1 = propertyAnimation.target.backgroundColor; - nativeArray = (Array).create(java.lang.Object, 2); - nativeArray[0] = propertyAnimation.target.backgroundColor ? java.lang.Integer.valueOf((propertyAnimation.target.backgroundColor).argb) : java.lang.Integer.valueOf(-1); - nativeArray[1] = java.lang.Integer.valueOf((propertyAnimation.value).argb); + nativeArray = Array.create(java.lang.Object, 2); + nativeArray[0] = propertyAnimation.target.backgroundColor ? java.lang.Integer.valueOf((propertyAnimation.target.backgroundColor).argb) : java.lang.Integer.valueOf(-1); + nativeArray[1] = java.lang.Integer.valueOf((propertyAnimation.value).argb); let animator = android.animation.ValueAnimator.ofObject(argbEvaluator, nativeArray); animator.addUpdateListener(new android.animation.ValueAnimator.AnimatorUpdateListener({ onAnimationUpdate(animator: android.animation.ValueAnimator) { let argb = (animator.getAnimatedValue()).intValue(); - propertyAnimation.target.style._setValue(styleModule.backgroundColorProperty, new color.Color(argb), valueSource); + propertyAnimation.target.style[backgroundColorProperty.cssName] = new Color(argb); } })); propertyUpdateCallbacks.push(checkAnimation(() => { - propertyAnimation.target.style._setValue(styleModule.backgroundColorProperty, propertyAnimation.value, valueSource); + propertyAnimation.target.style[backgroundColorProperty.cssName] = propertyAnimation.value; })); propertyResetCallbacks.push(checkAnimation(() => { - propertyAnimation.target.style._setValue(styleModule.backgroundColorProperty, originalValue1, valueSource); + propertyAnimation.target.style[backgroundColorProperty.cssName] = originalValue1; })); animators.push(animator); break; - case common.Properties.translate: - xyObjectAnimators = (Array).create(android.animation.Animator, 2); + case Properties.translate: + xyObjectAnimators = Array.create(android.animation.Animator, 2); - nativeArray = (Array).create("float", 1); + nativeArray = Array.create("float", 1); nativeArray[0] = propertyAnimation.value.x * density; xyObjectAnimators[0] = android.animation.ObjectAnimator.ofFloat(nativeView, "translationX", nativeArray); xyObjectAnimators[0].setRepeatCount(Animation._getAndroidRepeatCount(propertyAnimation.iterations)); - nativeArray = (Array).create("float", 1); + nativeArray = Array.create("float", 1); nativeArray[0] = propertyAnimation.value.y * density; xyObjectAnimators[1] = android.animation.ObjectAnimator.ofFloat(nativeView, "translationY", nativeArray); xyObjectAnimators[1].setRepeatCount(Animation._getAndroidRepeatCount(propertyAnimation.iterations)); @@ -246,13 +295,13 @@ export class Animation extends common.Animation implements definition.Animation originalValue2 = nativeView.getTranslationY(); propertyUpdateCallbacks.push(checkAnimation(() => { - propertyAnimation.target.style._setValue(styleModule.translateXProperty, propertyAnimation.value.x, valueSource); - propertyAnimation.target.style._setValue(styleModule.translateYProperty, propertyAnimation.value.y, valueSource); + propertyAnimation.target.style[translateXProperty.cssName] = propertyAnimation.value.x; + propertyAnimation.target.style[translateYProperty.cssName] = propertyAnimation.value.y; })); propertyResetCallbacks.push(checkAnimation(() => { - propertyAnimation.target.style._setValue(styleModule.translateXProperty, originalValue1, valueSource); - propertyAnimation.target.style._setValue(styleModule.translateYProperty, originalValue2, valueSource); + propertyAnimation.target.style[translateXProperty.cssName] = originalValue1; + propertyAnimation.target.style[translateYProperty.cssName] = originalValue2; })); animatorSet = new android.animation.AnimatorSet(); @@ -261,15 +310,15 @@ export class Animation extends common.Animation implements definition.Animation animators.push(animatorSet); break; - case common.Properties.scale: - xyObjectAnimators = (Array).create(android.animation.Animator, 2); + case Properties.scale: + xyObjectAnimators = Array.create(android.animation.Animator, 2); - nativeArray = (Array).create("float", 1); + nativeArray = Array.create("float", 1); nativeArray[0] = propertyAnimation.value.x; xyObjectAnimators[0] = android.animation.ObjectAnimator.ofFloat(nativeView, "scaleX", nativeArray); xyObjectAnimators[0].setRepeatCount(Animation._getAndroidRepeatCount(propertyAnimation.iterations)); - nativeArray = (Array).create("float", 1); + nativeArray = Array.create("float", 1); nativeArray[0] = propertyAnimation.value.y; xyObjectAnimators[1] = android.animation.ObjectAnimator.ofFloat(nativeView, "scaleY", nativeArray); xyObjectAnimators[1].setRepeatCount(Animation._getAndroidRepeatCount(propertyAnimation.iterations)); @@ -278,13 +327,13 @@ export class Animation extends common.Animation implements definition.Animation originalValue2 = nativeView.getScaleY(); propertyUpdateCallbacks.push(checkAnimation(() => { - propertyAnimation.target.style._setValue(styleModule.scaleXProperty, propertyAnimation.value.x, valueSource); - propertyAnimation.target.style._setValue(styleModule.scaleYProperty, propertyAnimation.value.y, valueSource); + propertyAnimation.target.style[scaleXProperty.cssName] = propertyAnimation.value.x; + propertyAnimation.target.style[scaleYProperty.cssName] = propertyAnimation.value.y; })); propertyResetCallbacks.push(checkAnimation(() => { - propertyAnimation.target.style._setValue(styleModule.scaleXProperty, originalValue1, valueSource); - propertyAnimation.target.style._setValue(styleModule.scaleYProperty, originalValue2, valueSource); + propertyAnimation.target.style[scaleXProperty.cssName] = originalValue1; + propertyAnimation.target.style[scaleYProperty.cssName] = originalValue2; })); animatorSet = new android.animation.AnimatorSet(); @@ -293,15 +342,15 @@ export class Animation extends common.Animation implements definition.Animation animators.push(animatorSet); break; - case common.Properties.rotate: + case Properties.rotate: originalValue1 = nativeView.getRotation(); - nativeArray = (Array).create("float", 1); + nativeArray = Array.create("float", 1); nativeArray[0] = propertyAnimation.value; propertyUpdateCallbacks.push(checkAnimation(() => { - propertyAnimation.target.style._setValue(styleModule.rotateProperty, propertyAnimation.value, valueSource); + propertyAnimation.target.style[rotateProperty.cssName] = propertyAnimation.value; })); propertyResetCallbacks.push(checkAnimation(() => { - propertyAnimation.target.style._setValue(styleModule.rotateProperty, originalValue1, valueSource); + propertyAnimation.target.style[rotateProperty.cssName] = originalValue1; })); animators.push(android.animation.ObjectAnimator.ofFloat(nativeView, "rotation", nativeArray)); break; @@ -310,9 +359,7 @@ export class Animation extends common.Animation implements definition.Animation throw new Error("Cannot animate " + propertyAnimation.property); } - let i = 0; - let length = animators.length; - for (; i < length; i++) { + for (let i = 0, length = animators.length; i < length; i++) { // Duration if (propertyAnimation.duration !== undefined) { @@ -351,7 +398,7 @@ export class Animation extends common.Animation implements definition.Animation private _enableHardwareAcceleration() { for (let i = 0, length = this._propertyAnimations.length; i < length; i++) { let cache = this._propertyAnimations[i].target._nativeView; - if (cache){ + if (cache) { let layerType = cache.getLayerType(); if (layerType !== android.view.View.LAYER_TYPE_HARDWARE) { cache.layerType = layerType; @@ -370,51 +417,4 @@ export class Animation extends common.Animation implements definition.Animation } } } -} - -let easeIn = lazy(() => new android.view.animation.AccelerateInterpolator(1)); -let easeOut = lazy(() => new android.view.animation.DecelerateInterpolator(1)); -let easeInOut = lazy(() => new android.view.animation.AccelerateDecelerateInterpolator()); -let linear = lazy(() => new android.view.animation.LinearInterpolator()); -let bounce = lazy(() => new android.view.animation.BounceInterpolator()); -export function _resolveAnimationCurve(curve: any): any { - switch (curve) { - case enums.AnimationCurve.easeIn: - if (trace.enabled) { - trace.write("Animation curve resolved to android.view.animation.AccelerateInterpolator(1).", trace.categories.Animation); - } - return easeIn(); - case enums.AnimationCurve.easeOut: - if (trace.enabled) { - trace.write("Animation curve resolved to android.view.animation.DecelerateInterpolator(1).", trace.categories.Animation); - } - return easeOut(); - case enums.AnimationCurve.easeInOut: - if (trace.enabled) { - trace.write("Animation curve resolved to android.view.animation.AccelerateDecelerateInterpolator().", trace.categories.Animation); - } - return easeInOut(); - case enums.AnimationCurve.linear: - if (trace.enabled) { - trace.write("Animation curve resolved to android.view.animation.LinearInterpolator().", trace.categories.Animation); - } - return linear(); - case enums.AnimationCurve.spring: - if (trace.enabled) { - trace.write("Animation curve resolved to android.view.animation.BounceInterpolator().", trace.categories.Animation); - } - return bounce(); - case enums.AnimationCurve.ease: - return (android).support.v4.view.animation.PathInterpolatorCompat.create(0.25, 0.1, 0.25, 1.0); - default: - if (trace.enabled) { - trace.write("Animation curve resolved to original: " + curve, trace.categories.Animation); - } - if (curve instanceof common.CubicBezierAnimationCurve) { - let animationCurve = curve; - let interpolator = (android).support.v4.view.animation.PathInterpolatorCompat.create(animationCurve.x1, animationCurve.y1, animationCurve.x2, animationCurve.y2); - return interpolator; - } - return curve; - } -} \ No newline at end of file +} \ No newline at end of file diff --git a/tns-core-modules/ui/animation/animation.d.ts b/tns-core-modules/ui/animation/animation.d.ts index 00b906f38..ddf76f200 100644 --- a/tns-core-modules/ui/animation/animation.d.ts +++ b/tns-core-modules/ui/animation/animation.d.ts @@ -1,7 +1,7 @@ declare module "ui/animation" { - import viewModule = require("ui/core/view"); - import colorModule = require("color"); - + import {View} from "ui/core/view"; + import {Color} from "color"; + /** * Defines animation options for the View.animate method. */ @@ -9,7 +9,7 @@ /** * The view whose property is to be animated. */ - target?: viewModule.View; + target?: View; /** * Animates the opacity of the view. Value should be a number between 0.0 and 1.0 @@ -19,7 +19,7 @@ /** * Animates the backgroundColor of the view. */ - backgroundColor?: colorModule.Color; + backgroundColor?: Color; /** * Animates the translate affine transform of the view. @@ -65,7 +65,6 @@ * Possible values are numeric values from 0 to 1 */ export class CubicBezierAnimationCurve { - public x1: number; public y1: number; public x2: number; @@ -101,9 +100,6 @@ public play: () => AnimationPromise; public cancel: () => void; public isPlaying: boolean; + public _resolveAnimationCurve(curve: any): any; } - - //@private - export function _resolveAnimationCurve(curve: any): any; - //@endprivate -} +} \ No newline at end of file diff --git a/tns-core-modules/ui/animation/animation.ios.ts b/tns-core-modules/ui/animation/animation.ios.ts index 12b39d7d7..ad264e69f 100644 --- a/tns-core-modules/ui/animation/animation.ios.ts +++ b/tns-core-modules/ui/animation/animation.ios.ts @@ -1,21 +1,20 @@ -import definition = require("ui/animation"); -import common = require("./animation-common"); -import viewModule = require("ui/core/view"); -import trace = require("trace"); -import enums = require("ui/enums"); -import style = require("ui/styling/style"); -import dependencyObservable = require("ui/core/dependency-observable"); +import {AnimationDefinition} from "ui/animation"; +import {AnimationBase, Properties, PropertyAnimation, CubicBezierAnimationCurve, AnimationPromise} from "./animation-common"; +import {View} from "ui/core/view"; +import {AnimationCurve} from "ui/enums"; +import {opacityProperty, backgroundColorProperty, rotateProperty, + translateXProperty, translateYProperty, + scaleXProperty, scaleYProperty } from "ui/styling/style"; +import * as trace from "trace"; -import * as utils from "utils/utils"; - -global.moduleMerge(common, exports); +export * from "./animation-common"; let _transform = "_transform"; let _skip = "_skip"; let FLT_MAX = 340282346638528859811704183484516925440.000000; -declare var CASpringAnimation:any; +declare var CASpringAnimation: any; class AnimationInfo { public propertyNameToAnimate: string; @@ -26,16 +25,16 @@ class AnimationInfo { public delay: number; } -interface PropertyAnimationInfo extends common.PropertyAnimation { +interface PropertyAnimationInfo extends PropertyAnimation { _propertyResetCallback?: any; _originalValue?: any; } -interface AnimationDefinitionInternal extends definition.AnimationDefinition { +interface AnimationDefinitionInternal extends AnimationDefinition { valueSource?: number; } -interface IOSView extends viewModule.View { +interface IOSView extends View { _suspendPresentationLayerUpdates(); _resumePresentationLayerUpdates(); _isPresentationLayerUpdateSuspeneded(); @@ -62,39 +61,40 @@ class AnimationDelegateImpl extends NSObject implements CAAnimationDelegate { animationDidStart(anim: CAAnimation): void { let value = this._propertyAnimation.value; - let valueSource = this._valueSource || dependencyObservable.ValueSource.Local; + // let valueSource = this._valueSource || dependencyObservable.ValueSource.Local; + let setLocal = true; let targetStyle = this._propertyAnimation.target.style; (this._propertyAnimation.target)._suspendPresentationLayerUpdates(); switch (this._propertyAnimation.property) { - case common.Properties.backgroundColor: - targetStyle._setValue(style.backgroundColorProperty, value, valueSource); + case Properties.backgroundColor: + targetStyle[setLocal ? backgroundColorProperty.name : backgroundColorProperty.cssName] = value; break; - case common.Properties.opacity: - targetStyle._setValue(style.opacityProperty, value, valueSource); + case Properties.opacity: + targetStyle[setLocal ? opacityProperty.name : opacityProperty.cssName] = value; break; - case common.Properties.rotate: - targetStyle._setValue(style.rotateProperty, value, valueSource); + case Properties.rotate: + targetStyle[setLocal ? rotateProperty.name : rotateProperty.cssName] = value; break; - case common.Properties.translate: - targetStyle._setValue(style.translateXProperty, value.x, valueSource); - targetStyle._setValue(style.translateYProperty, value.y, valueSource); + case Properties.translate: + targetStyle[setLocal ? translateXProperty.name : translateXProperty.cssName] = value; + targetStyle[setLocal ? translateYProperty.name : translateYProperty.cssName] = value; break; - case common.Properties.scale: - targetStyle._setValue(style.scaleXProperty, value.x === 0 ? 0.001 : value.x, valueSource); - targetStyle._setValue(style.scaleYProperty, value.y === 0 ? 0.001 : value.y, valueSource); + case Properties.scale: + targetStyle[setLocal ? scaleXProperty.name : scaleXProperty.cssName] = value.x === 0 ? 0.001 : value.x; + targetStyle[setLocal ? scaleYProperty.name : scaleYProperty.cssName] = value.y === 0 ? 0.001 : value.y; break; case _transform: - if (value[common.Properties.translate] !== undefined) { - targetStyle._setValue(style.translateXProperty, value[common.Properties.translate].x, valueSource); - targetStyle._setValue(style.translateYProperty, value[common.Properties.translate].y, valueSource); + if (value[Properties.translate] !== undefined) { + targetStyle[setLocal ? translateXProperty.name : translateXProperty.cssName] = value[Properties.translate].x; + targetStyle[setLocal ? translateYProperty.name : translateYProperty.cssName] = value[Properties.translate].y; } - if (value[common.Properties.scale] !== undefined) { - let x = value[common.Properties.scale].x; - let y = value[common.Properties.scale].y; - targetStyle._setValue(style.scaleXProperty, x === 0 ? 0.001 : x, valueSource); - targetStyle._setValue(style.scaleYProperty, y === 0 ? 0.001 : y, valueSource); + if (value[Properties.scale] !== undefined) { + let x = value[Properties.scale].x; + let y = value[Properties.scale].y; + targetStyle[setLocal ? scaleXProperty.name : scaleXProperty.cssName] = x === 0 ? 0.001 : x; + targetStyle[setLocal ? scaleYProperty.name : scaleYProperty.cssName] = y === 0 ? 0.001 : y; } break; } @@ -112,35 +112,13 @@ class AnimationDelegateImpl extends NSObject implements CAAnimationDelegate { } } -export class Animation extends common.Animation implements definition.Animation { +export class Animation extends AnimationBase { private _iOSAnimationFunction: Function; private _finishedAnimations: number; private _cancelledAnimations: number; private _mergedPropertyAnimations: Array; private _valueSource: number; - public play(): definition.AnimationPromise { - let animationFinishedPromise = super.play(); - this._finishedAnimations = 0; - this._cancelledAnimations = 0; - this._iOSAnimationFunction(); - return animationFinishedPromise; - } - - public cancel(): void { - super.cancel(); - - let i = 0; - let length = this._mergedPropertyAnimations.length; - for (; i < length; i++) { - let propertyAnimation = this._mergedPropertyAnimations[i]; - propertyAnimation.target._nativeView.layer.removeAllAnimations(); - if (propertyAnimation._propertyResetCallback) { - propertyAnimation._propertyResetCallback(propertyAnimation._originalValue, this._valueSource); - } - } - } - constructor(animationDefinitions: Array, playSequentially?: boolean) { super(animationDefinitions, playSequentially); @@ -199,7 +177,55 @@ export class Animation extends common.Animation implements definition.Animation this._iOSAnimationFunction = Animation._createiOSAnimationFunction(this._mergedPropertyAnimations, 0, this._playSequentially, this._valueSource, animationFinishedCallback); } - private static _createiOSAnimationFunction(propertyAnimations: Array, index: number, playSequentially: boolean, valueSource: number, finishedCallback: (cancelled?: boolean) => void): Function { + public play(): AnimationPromise { + let animationFinishedPromise = super.play(); + this._finishedAnimations = 0; + this._cancelledAnimations = 0; + this._iOSAnimationFunction(); + return animationFinishedPromise; + } + + public cancel(): void { + super.cancel(); + + let i = 0; + let length = this._mergedPropertyAnimations.length; + for (; i < length; i++) { + let propertyAnimation = this._mergedPropertyAnimations[i]; + propertyAnimation.target._nativeView.layer.removeAllAnimations(); + if (propertyAnimation._propertyResetCallback) { + propertyAnimation._propertyResetCallback(propertyAnimation._originalValue, this._valueSource); + } + } + } + + public _resolveAnimationCurve(curve: string | CubicBezierAnimationCurve | CAMediaTimingFunction): CAMediaTimingFunction { + switch (curve) { + case AnimationCurve.easeIn: + return CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseIn); + case AnimationCurve.easeOut: + return CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseOut); + case AnimationCurve.easeInOut: + return CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut); + case AnimationCurve.linear: + return CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionLinear); + case AnimationCurve.spring: + return curve; + case AnimationCurve.ease: + return CAMediaTimingFunction.functionWithControlPoints(0.25, 0.1, 0.25, 1.0); + default: + if (curve instanceof CAMediaTimingFunction) { + return curve; + } + else if (curve instanceof CubicBezierAnimationCurve) { + let animationCurve = curve; + return CAMediaTimingFunction.functionWithControlPoints(animationCurve.x1, animationCurve.y1, animationCurve.x2, animationCurve.y2); + } + return undefined; + } + } + + private static _createiOSAnimationFunction(propertyAnimations: Array, index: number, playSequentially: boolean, valueSource: number, finishedCallback: (cancelled?: boolean) => void): Function { return (cancelled?: boolean) => { if (cancelled && finishedCallback) { @@ -210,16 +236,16 @@ export class Animation extends common.Animation implements definition.Animation return; } - let animation = propertyAnimations[index]; - let args = Animation._getNativeAnimationArguments(animation, valueSource); + let animation = propertyAnimations[index]; + let args = Animation._getNativeAnimationArguments(animation, valueSource); - if (animation.curve === enums.AnimationCurve.spring) { - Animation._createNativeSpringAnimation(propertyAnimations, index, playSequentially, args, animation, valueSource, finishedCallback); - } - else { - Animation._createNativeAnimation(propertyAnimations, index, playSequentially, args, animation, valueSource, finishedCallback); - } - } + if (animation.curve === AnimationCurve.spring) { + Animation._createNativeSpringAnimation(propertyAnimations, index, playSequentially, args, animation, valueSource, finishedCallback); + } + else { + Animation._createNativeAnimation(propertyAnimations, index, playSequentially, args, animation, valueSource, finishedCallback); + } + } } private static _getNativeAnimationArguments(animation: PropertyAnimationInfo, valueSource: number): AnimationInfo { @@ -232,15 +258,16 @@ export class Animation extends common.Animation implements definition.Animation let tempRotate = (animation.target.rotate || 0) * Math.PI / 180; let abs; - if (valueSource === undefined) { - valueSource = dependencyObservable.ValueSource.Local; - } + let setLocal = true; + // if (valueSource === undefined) { + // valueSource = dependencyObservable.ValueSource.Local; + // } switch (animation.property) { - case common.Properties.backgroundColor: + case Properties.backgroundColor: animation._originalValue = animation.target.backgroundColor; animation._propertyResetCallback = (value, valueSource) => { - animation.target.style._setValue(style.backgroundColorProperty, value, valueSource); + animation.target.style[setLocal ? backgroundColorProperty.name : backgroundColorProperty.cssName] = value; }; originalValue = nativeView.layer.backgroundColor; if (nativeView instanceof UILabel) { @@ -248,17 +275,17 @@ export class Animation extends common.Animation implements definition.Animation } value = value.CGColor; break; - case common.Properties.opacity: + case Properties.opacity: animation._originalValue = animation.target.opacity; animation._propertyResetCallback = (value, valueSource) => { - animation.target.style._setValue(style.opacityProperty, value, valueSource); + animation.target.style[setLocal ? opacityProperty.name : opacityProperty.cssName] = value; }; originalValue = nativeView.layer.opacity; break; - case common.Properties.rotate: + case Properties.rotate: animation._originalValue = animation.target.rotate !== undefined ? animation.target.rotate : 0; animation._propertyResetCallback = (value, valueSource) => { - animation.target.style._setValue(style.rotateProperty, value, valueSource); + animation.target.style[setLocal ? rotateProperty.name : rotateProperty.cssName] = value; }; propertyNameToAnimate = "transform.rotation"; originalValue = nativeView.layer.valueForKeyPath("transform.rotation"); @@ -271,17 +298,17 @@ export class Animation extends common.Animation implements definition.Animation originalValue = tempRotate; } break; - case common.Properties.translate: + case Properties.translate: animation._originalValue = { x: animation.target.translateX, y: animation.target.translateY }; animation._propertyResetCallback = (value, valueSource) => { - animation.target.style._setValue(style.translateXProperty, value.x, valueSource); - animation.target.style._setValue(style.translateYProperty, value.y, valueSource); + animation.target.style[setLocal ? translateXProperty.name : translateXProperty.cssName] = value.x; + animation.target.style[setLocal ? translateYProperty.name : translateYProperty.cssName] = value.y; }; propertyNameToAnimate = "transform"; originalValue = NSValue.valueWithCATransform3D(nativeView.layer.transform); value = NSValue.valueWithCATransform3D(CATransform3DTranslate(nativeView.layer.transform, value.x, value.y, 0)); break; - case common.Properties.scale: + case Properties.scale: if (value.x === 0) { value.x = 0.001; } @@ -290,8 +317,8 @@ export class Animation extends common.Animation implements definition.Animation } animation._originalValue = { x: animation.target.scaleX, y: animation.target.scaleY }; animation._propertyResetCallback = (value, valueSource) => { - animation.target.style._setValue(style.scaleXProperty, value.x, valueSource); - animation.target.style._setValue(style.scaleYProperty, value.y, valueSource); + animation.target.style[setLocal ? scaleXProperty.name : scaleXProperty.cssName] = value.x; + animation.target.style[setLocal ? scaleYProperty.name : scaleYProperty.cssName] = value.y; }; propertyNameToAnimate = "transform"; originalValue = NSValue.valueWithCATransform3D(nativeView.layer.transform); @@ -299,13 +326,15 @@ export class Animation extends common.Animation implements definition.Animation break; case _transform: originalValue = NSValue.valueWithCATransform3D(nativeView.layer.transform); - animation._originalValue = { xs: animation.target.scaleX, ys: animation.target.scaleY, - xt: animation.target.translateX, yt: animation.target.translateY }; + animation._originalValue = { + xs: animation.target.scaleX, ys: animation.target.scaleY, + xt: animation.target.translateX, yt: animation.target.translateY + }; animation._propertyResetCallback = (value, valueSource) => { - animation.target.style._setValue(style.translateXProperty, value.xt, valueSource); - animation.target.style._setValue(style.translateYProperty, value.yt, valueSource); - animation.target.style._setValue(style.scaleXProperty, value.xs, valueSource); - animation.target.style._setValue(style.scaleYProperty, value.ys, valueSource); + animation.target.style[setLocal ? translateXProperty.name : translateXProperty.cssName] = value.xt; + animation.target.style[setLocal ? translateYProperty.name : translateYProperty.cssName] = value.yt; + animation.target.style[setLocal ? scaleXProperty.name : scaleXProperty.cssName] = value.xs; + animation.target.style[setLocal ? scaleYProperty.name : scaleYProperty.cssName] = value.ys; }; propertyNameToAnimate = "transform"; value = NSValue.valueWithCATransform3D(Animation._createNativeAffineTransform(animation)); @@ -344,7 +373,7 @@ export class Animation extends common.Animation implements definition.Animation }; } - private static _createNativeAnimation(propertyAnimations: Array, index: number, playSequentially: boolean, args: AnimationInfo, animation: common.PropertyAnimation, valueSource: number, finishedCallback: (cancelled?: boolean) => void) { + private static _createNativeAnimation(propertyAnimations: Array, index: number, playSequentially: boolean, args: AnimationInfo, animation: PropertyAnimation, valueSource: number, finishedCallback: (cancelled?: boolean) => void) { let nativeView = animation.target._nativeView; let nativeAnimation = CABasicAnimation.animationWithKeyPath(args.propertyNameToAnimate); @@ -362,7 +391,7 @@ export class Animation extends common.Animation implements definition.Animation } let animationDelegate = AnimationDelegateImpl.initWithFinishedCallback(finishedCallback, animation, valueSource); - nativeAnimation.delegate = animationDelegate; + nativeAnimation.setValueForKey(animationDelegate, "delegate"); nativeView.layer.addAnimationForKey(nativeAnimation, args.propertyNameToAnimate); @@ -407,64 +436,64 @@ export class Animation extends common.Animation implements definition.Animation } switch (animation.property) { - case common.Properties.backgroundColor: - animation.target.backgroundColor = args.toValue; - break; - case common.Properties.opacity: - animation.target.opacity = args.toValue; - break; - case common.Properties.rotate: - nativeView.layer.setValueForKey(args.toValue, args.propertyNameToAnimate); - break; - case _transform: - animation._originalValue = nativeView.layer.transform; - nativeView.layer.setValueForKey(args.toValue, args.propertyNameToAnimate); - animation._propertyResetCallback = function (value) { - nativeView.layer.transform = value; - } - break; + case Properties.backgroundColor: + animation.target.backgroundColor = args.toValue; + break; + case Properties.opacity: + animation.target.opacity = args.toValue; + break; + case Properties.rotate: + nativeView.layer.setValueForKey(args.toValue, args.propertyNameToAnimate); + break; + case _transform: + animation._originalValue = nativeView.layer.transform; + nativeView.layer.setValueForKey(args.toValue, args.propertyNameToAnimate); + animation._propertyResetCallback = function (value) { + nativeView.layer.transform = value; + } + break; } - }, function (finished: boolean) { - if (finished) { - if (animation.property === _transform) { - if (animation.value[common.Properties.translate] !== undefined) { - animation.target.translateX = animation.value[common.Properties.translate].x; - animation.target.translateY = animation.value[common.Properties.translate].y; - } - if (animation.value[common.Properties.scale] !== undefined) { - animation.target.scaleX = animation.value[common.Properties.scale].x; - animation.target.scaleY = animation.value[common.Properties.scale].y; + }, function (finished: boolean) { + if (finished) { + if (animation.property === _transform) { + if (animation.value[Properties.translate] !== undefined) { + animation.target.translateX = animation.value[Properties.translate].x; + animation.target.translateY = animation.value[Properties.translate].y; + } + if (animation.value[Properties.scale] !== undefined) { + animation.target.scaleX = animation.value[Properties.scale].x; + animation.target.scaleY = animation.value[Properties.scale].y; + } } } - } - else { - if (animation._propertyResetCallback) { - animation._propertyResetCallback(animation._originalValue); + else { + if (animation._propertyResetCallback) { + animation._propertyResetCallback(animation._originalValue); + } } - } - if (finishedCallback) { - let cancelled = !finished; - finishedCallback(cancelled); - } - if (finished && nextAnimation) { - nextAnimation(); - } - }); + if (finishedCallback) { + let cancelled = !finished; + finishedCallback(cancelled); + } + if (finished && nextAnimation) { + nextAnimation(); + } + }); } - private static _createNativeAffineTransform(animation: common.PropertyAnimation): CATransform3D { + private static _createNativeAffineTransform(animation: PropertyAnimation): CATransform3D { let value = animation.value; let result: CATransform3D = CATransform3DIdentity; - if (value[common.Properties.translate] !== undefined) { - let x = value[common.Properties.translate].x; - let y = value[common.Properties.translate].y; + if (value[Properties.translate] !== undefined) { + let x = value[Properties.translate].x; + let y = value[Properties.translate].y; result = CATransform3DTranslate(result, x, y, 0); } - if (value[common.Properties.scale] !== undefined) { - let x = value[common.Properties.scale].x; - let y = value[common.Properties.scale].y; + if (value[Properties.scale] !== undefined) { + let x = value[Properties.scale].x; + let y = value[Properties.scale].y; result = CATransform3DScale(result, x === 0 ? 0.001 : x, y === 0 ? 0.001 : y, 1); } @@ -473,11 +502,11 @@ export class Animation extends common.Animation implements definition.Animation private static _isAffineTransform(property: string): boolean { return property === _transform - || property === common.Properties.translate - || property === common.Properties.scale; + || property === Properties.translate + || property === Properties.scale; } - private static _canBeMerged(animation1: common.PropertyAnimation, animation2: common.PropertyAnimation) { + private static _canBeMerged(animation1: PropertyAnimation, animation2: PropertyAnimation) { let result = Animation._isAffineTransform(animation1.property) && Animation._isAffineTransform(animation2.property) && @@ -489,8 +518,8 @@ export class Animation extends common.Animation implements definition.Animation return result; } - private static _mergeAffineTransformAnimations(propertyAnimations: Array): Array { - let result = new Array(); + private static _mergeAffineTransformAnimations(propertyAnimations: Array): Array { + let result = new Array(); let i = 0; let j; @@ -512,7 +541,7 @@ export class Animation extends common.Animation implements definition.Animation // rotate: 90, // scale: {x: 2, y: 2 } // } - let newTransformAnimation: common.PropertyAnimation = { + let newTransformAnimation: PropertyAnimation = { target: propertyAnimations[i].target, property: _transform, value: {}, @@ -526,7 +555,7 @@ export class Animation extends common.Animation implements definition.Animation } newTransformAnimation.value[propertyAnimations[i].property] = propertyAnimations[i].value; if (trace.enabled) { - trace.write("Created new transform animation: " + common.Animation._getAnimationInfo(newTransformAnimation), trace.categories.Animation); + trace.write("Created new transform animation: " + Animation._getAnimationInfo(newTransformAnimation), trace.categories.Animation); } // Merge all compatible affine transform animations to the right into this new animation. @@ -535,7 +564,7 @@ export class Animation extends common.Animation implements definition.Animation for (; j < length; j++) { if (Animation._canBeMerged(propertyAnimations[i], propertyAnimations[j])) { if (trace.enabled) { - trace.write("Merging animations: " + common.Animation._getAnimationInfo(newTransformAnimation) + " + " + common.Animation._getAnimationInfo(propertyAnimations[j]) + ";", trace.categories.Animation); + trace.write("Merging animations: " + Animation._getAnimationInfo(newTransformAnimation) + " + " + Animation._getAnimationInfo(propertyAnimations[j]) + ";", trace.categories.Animation); } newTransformAnimation.value[propertyAnimations[j].property] = propertyAnimations[j].value; // Mark that it has been merged so we can skip it on our outer loop. @@ -551,33 +580,7 @@ export class Animation extends common.Animation implements definition.Animation } } -export function _resolveAnimationCurve(curve: any): any { - switch (curve) { - case enums.AnimationCurve.easeIn: - return CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseIn); - case enums.AnimationCurve.easeOut: - return CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseOut); - case enums.AnimationCurve.easeInOut: - return CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut); - case enums.AnimationCurve.linear: - return CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionLinear); - case enums.AnimationCurve.spring: - return curve; - case enums.AnimationCurve.ease: - return CAMediaTimingFunction.functionWithControlPoints(0.25, 0.1, 0.25, 1.0); - default: - if (curve instanceof CAMediaTimingFunction) { - return curve; - } - else if (curve instanceof common.CubicBezierAnimationCurve) { - let animationCurve = curve; - return CAMediaTimingFunction.functionWithControlPoints(animationCurve.x1, animationCurve.y1, animationCurve.x2, animationCurve.y2); - } - return undefined; - } -} - -export function _getTransformMismatchErrorMessage(view: viewModule.View): string { +export function _getTransformMismatchErrorMessage(view: View): string { // Order is important: translate, rotate, scale let result: CGAffineTransform = CGAffineTransformIdentity; result = CGAffineTransformTranslate(result, view.translateX || 0, view.translateY || 0); diff --git a/tns-core-modules/ui/animation/keyframe-animation.d.ts b/tns-core-modules/ui/animation/keyframe-animation.d.ts index 15e385c3b..93efe978c 100644 --- a/tns-core-modules/ui/animation/keyframe-animation.d.ts +++ b/tns-core-modules/ui/animation/keyframe-animation.d.ts @@ -1,6 +1,6 @@ declare module "ui/animation/keyframe-animation" { -import view = require("ui/core/view"); + import {View} from "ui/core/view"; export interface KeyframeDeclaration { property: string; @@ -84,7 +84,7 @@ import view = require("ui/core/view"); /** * Plays the animation. */ - public play: (view: view.View) => Promise; + public play: (view: View) => Promise; /** * Cancels a playing animation. @@ -94,6 +94,6 @@ import view = require("ui/core/view"); /** * Creates a keyframe animation from animation definition. */ - public static keyframeAnimationFromInfo(info: KeyframeAnimationInfo, valueSourceModifier: number); + public static keyframeAnimationFromInfo(info: KeyframeAnimationInfo); } } \ No newline at end of file diff --git a/tns-core-modules/ui/animation/keyframe-animation.ts b/tns-core-modules/ui/animation/keyframe-animation.ts index 5626aec3e..d53b95dba 100644 --- a/tns-core-modules/ui/animation/keyframe-animation.ts +++ b/tns-core-modules/ui/animation/keyframe-animation.ts @@ -1,32 +1,35 @@ -import definition = require("ui/animation/keyframe-animation"); -import animationModule = require("ui/animation"); -import view = require("ui/core/view"); -import enums = require("ui/enums"); -import style = require("ui/styling/style"); +import {KeyframeDeclaration as KeyframeDeclarationDefinition, + KeyframeInfo as KeyframeInfoDefinition, + KeyframeAnimationInfo as KeyframeAnimationInfoDefinition, + KeyframeAnimation as KeyframeAnimationDefinition} from "ui/animation/keyframe-animation"; +import {Animation} from "ui/animation"; +import {View} from "ui/core/view"; +import {AnimationCurve} from "ui/enums"; +import {unsetValue} from "ui/core/dependency-observable"; -export class KeyframeDeclaration implements definition.KeyframeDeclaration { +export class KeyframeDeclaration implements KeyframeDeclarationDefinition { public property: string; public value: any; } -export class KeyframeInfo implements definition.KeyframeInfo { +export class KeyframeInfo implements KeyframeInfoDefinition { public duration: number; public curve: any; public declarations: Array; } -export class KeyframeAnimationInfo implements definition.KeyframeAnimationInfo { +export class KeyframeAnimationInfo implements KeyframeAnimationInfoDefinition { public name: string = ""; public duration: number = 0.3; public delay: number = 0; public iterations: number = 1; - public curve: any = enums.AnimationCurve.ease; + public curve: any = AnimationCurve.ease; public isForwards: boolean = false; public isReverse: boolean = false; public keyframes: Array; } -export class KeyframeAnimation { +export class KeyframeAnimation implements KeyframeAnimationDefinition { public animations: Array; public delay: number = 0; public iterations: number = 1; @@ -35,25 +38,25 @@ export class KeyframeAnimation { private _reject; private _isPlaying: boolean; private _isForwards: boolean; - private _nativeAnimations: Array; - private _target: view.View; + private _nativeAnimations: Array; + private _target: View; - public static keyframeAnimationFromInfo(info: KeyframeAnimationInfo, valueSourceModifier: number) { + public static keyframeAnimationFromInfo(info: KeyframeAnimationInfo) { let animations = new Array(); let length = info.keyframes.length; let startDuration = 0; if (info.isReverse) { - for (let index = length - 1; index >= 0; index --) { + for (let index = length - 1; index >= 0; index--) { let keyframe = info.keyframes[index]; - startDuration = KeyframeAnimation.parseKeyframe(info, keyframe, animations, startDuration, valueSourceModifier); + startDuration = KeyframeAnimation.parseKeyframe(info, keyframe, animations, startDuration); } } else { - for (let index = 0; index < length; index ++) { + for (let index = 0; index < length; index++) { let keyframe = info.keyframes[index]; - startDuration = KeyframeAnimation.parseKeyframe(info, keyframe, animations, startDuration, valueSourceModifier); + startDuration = KeyframeAnimation.parseKeyframe(info, keyframe, animations, startDuration); } - for (let index = length - 1; index > 0; index --) { + for (let index = length - 1; index > 0; index--) { let a1 = animations[index]; let a2 = animations[index - 1]; if (a2["curve"] !== undefined) { @@ -76,7 +79,7 @@ export class KeyframeAnimation { return animation; } - private static parseKeyframe(info: KeyframeAnimationInfo, keyframe: KeyframeInfo, animations: Array, startDuration: number, valueSourceModifier: number): number { + private static parseKeyframe(info: KeyframeAnimationInfo, keyframe: KeyframeInfo, animations: Array, startDuration: number): number { let animation = {}; for (let declaration of keyframe.declarations) { animation[declaration.property] = declaration.value; @@ -92,7 +95,6 @@ export class KeyframeAnimation { animation["duration"] = info.isReverse ? info.duration - duration : duration; animation["curve"] = keyframe.curve; animation["forceLayer"] = true; - animation["valueSource"] = valueSourceModifier; animations.push(animation); return startDuration; } @@ -118,7 +120,7 @@ export class KeyframeAnimation { } } - public play(view: view.View): Promise { + public play(view: View): Promise { if (this._isPlaying) { throw new Error("Animation is already playing."); } @@ -129,7 +131,7 @@ export class KeyframeAnimation { }); this._isPlaying = true; - this._nativeAnimations = new Array(); + this._nativeAnimations = new Array(); this._target = view; if (this.delay !== 0) { @@ -142,30 +144,29 @@ export class KeyframeAnimation { return animationFinishedPromise; } - private animate(view: view.View, index: number, iterations: number) { + private animate(view: View, index: number, iterations: number) { if (!this._isPlaying) { return; } if (index === 0) { let animation = this.animations[0]; - let modifier = animation["valueSource"]; if ("backgroundColor" in animation) { - view.style._setValue(style.backgroundColorProperty, animation["backgroundColor"], modifier); + view.style[`css-background-color`] = animation["backgroundColor"]; } if ("scale" in animation) { - view.style._setValue(style.scaleXProperty, animation["scale"].x, modifier); - view.style._setValue(style.scaleYProperty, animation["scale"].y, modifier); + view.style["css-scaleX"] = animation["scale"].x; + view.style["css-scaleY"] = animation["scale"].y; } if ("translate" in animation) { - view.style._setValue(style.translateXProperty, animation["translate"].x, modifier); - view.style._setValue(style.translateYProperty, animation["translate"].y, modifier); + view.style["css-translateX"] = animation["translate"].x; + view.style["css-translateY"] = animation["translate"].y; } if ("rotate" in animation) { - view.style._setValue(style.rotateProperty, animation["rotate"], modifier); + view.style["css-rotate"] = animation["rotate"]; } if ("opacity" in animation) { - view.style._setValue(style.opacityProperty, animation["opacity"], modifier); + view.style["css-opacity"] = animation["opacity"]; } setTimeout(() => this.animate(view, 1, iterations), 1); @@ -186,7 +187,7 @@ export class KeyframeAnimation { else { let animationDef = this.animations[index]; (animationDef).target = view; - let animation = new animationModule.Animation([animationDef]); + let animation = new Animation([animationDef]); animation.play().then(() => { this.animate(view, index + 1, iterations); }); @@ -195,37 +196,36 @@ export class KeyframeAnimation { } public _resolveAnimationFinishedPromise() { - this._nativeAnimations = new Array(); + this._nativeAnimations = new Array(); this._isPlaying = false; this._target = null; this._resolve(); } public _rejectAnimationFinishedPromise() { - this._nativeAnimations = new Array(); + this._nativeAnimations = new Array(); this._isPlaying = false; this._target = null; this._reject(new Error("Animation cancelled.")); } - private _resetAnimationValues(view: view.View, animation: Object) { - let modifier = animation["valueSource"]; + private _resetAnimationValues(view: View, animation: Object) { if ("backgroundColor" in animation) { - view.style._resetValue(style.backgroundColorProperty, modifier); + view.style[`css-background-color`] = unsetValue; } if ("scale" in animation) { - view.style._resetValue(style.scaleXProperty, modifier); - view.style._resetValue(style.scaleYProperty, modifier); + view.style["css-scaleX"] = animation["scale"].x; + view.style["css-scaleY"] = animation["scale"].y; } if ("translate" in animation) { - view.style._resetValue(style.translateXProperty, modifier); - view.style._resetValue(style.translateYProperty, modifier); + view.style["css-translateX"] = animation["translate"].x; + view.style["css-translateY"] = animation["translate"].y; } if ("rotate" in animation) { - view.style._resetValue(style.rotateProperty, modifier); + view.style["css-rotate"] = animation["rotate"]; } if ("opacity" in animation) { - view.style._resetValue(style.opacityProperty, modifier); + view.style["css-opacity"] = animation["opacity"]; } } -} +} \ No newline at end of file diff --git a/tns-core-modules/ui/border/border.d.ts b/tns-core-modules/ui/border/border.d.ts index 8e81abba6..9fe7102ec 100644 --- a/tns-core-modules/ui/border/border.d.ts +++ b/tns-core-modules/ui/border/border.d.ts @@ -2,8 +2,8 @@ * Contains the Border class, which represents a UI border component. */ declare module "ui/border" { - import {ContentView} from "ui/content-view"; import {Color} from "color"; + import {ContentView} from "ui/content-view"; /** * Represents a UI border component. diff --git a/tns-core-modules/ui/border/border.ts b/tns-core-modules/ui/border/border.ts index 0a0b0c649..fc86762ec 100644 --- a/tns-core-modules/ui/border/border.ts +++ b/tns-core-modules/ui/border/border.ts @@ -1,13 +1,13 @@ -import definition = require("ui/border"); -import contentView = require("ui/content-view"); -import viewModule = require("ui/core/view"); -import utils = require("utils/utils"); -import types = require("utils/types"); +import {Border as BorderDefinition} from "ui/border"; +import {View} from "ui/core/view"; +import {ContentView} from "ui/content-view"; +import {layout} from "utils/utils"; +import {isNumber} from "utils/types"; @Deprecated -export class Border extends contentView.ContentView implements definition.Border { +export class Border extends ContentView implements BorderDefinition { get cornerRadius(): number { - if (types.isNumber(this.borderRadius)){ + if (isNumber(this.borderRadius)){ return this.borderRadius; } return 0; @@ -17,36 +17,36 @@ export class Border extends contentView.ContentView implements definition.Border } public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void { - var width = utils.layout.getMeasureSpecSize(widthMeasureSpec); - var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec); + let width = layout.getMeasureSpecSize(widthMeasureSpec); + let widthMode = layout.getMeasureSpecMode(widthMeasureSpec); - var height = utils.layout.getMeasureSpecSize(heightMeasureSpec); - var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec); + let height = layout.getMeasureSpecSize(heightMeasureSpec); + let heightMode = layout.getMeasureSpecMode(heightMeasureSpec); - var density = utils.layout.getDisplayDensity(); + let density = utils.layout.getDisplayDensity(); let borderWidth = 0; if (types.isNumber(this.borderWidth)){ borderWidth = this.borderWidth; } - var borderSize = (2 * borderWidth) * density; + let borderSize = (2 * borderWidth) * density; - var result = viewModule.View.measureChild(this, this.layoutView, - utils.layout.makeMeasureSpec(width - borderSize, widthMode), - utils.layout.makeMeasureSpec(height - borderSize, heightMode)); + let result = View.measureChild(this, this.layoutView, + layout.makeMeasureSpec(width - borderSize, widthMode), + layout.makeMeasureSpec(height - borderSize, heightMode)); - var widthAndState = viewModule.View.resolveSizeAndState(result.measuredWidth + borderSize, width, widthMode, 0); - var heightAndState = viewModule.View.resolveSizeAndState(result.measuredHeight + borderSize, height, heightMode, 0); + let widthAndState = View.resolveSizeAndState(result.measuredWidth + borderSize, width, widthMode, 0); + let heightAndState = View.resolveSizeAndState(result.measuredHeight + borderSize, height, heightMode, 0); this.setMeasuredDimension(widthAndState, heightAndState); } public onLayout(left: number, top: number, right: number, bottom: number): void { - var density = utils.layout.getDisplayDensity(); + let density = utils.layout.getDisplayDensity(); let borderWidth = 0; if (types.isNumber(this.borderWidth)){ borderWidth = this.borderWidth; } - var borderSize = borderWidth * density; + let borderSize = borderWidth * density; viewModule.View.layoutChild(this, this.layoutView, borderSize, borderSize, right - left - borderSize, bottom - top - borderSize); } } \ No newline at end of file diff --git a/tns-core-modules/ui/button/button-common.ts b/tns-core-modules/ui/button/button-common.ts index 4657e23ed..48d3095d0 100644 --- a/tns-core-modules/ui/button/button-common.ts +++ b/tns-core-modules/ui/button/button-common.ts @@ -1,96 +1,15 @@ -import {Property, PropertyMetadataSettings, PropertyChangeData} from "ui/core/dependency-observable"; -import view = require("ui/core/view"); -import definition = require("ui/button"); -import proxy = require("ui/core/proxy"); -import formattedString = require("text/formatted-string"); -import observable = require("data/observable"); -import * as weakEventListenerModule from "ui/core/weak-event-listener"; +import {Button as ButtonDefinition} from "ui/button"; +import {TextBase} from "../text-base/text-base-common"; import {WhiteSpace} from "ui/enums"; -import {isAndroid} from "platform"; - -// on Android we explicitly set propertySettings to None because android will invalidate its layout (skip unnecessary native call). -let AffectsLayout = isAndroid ? PropertyMetadataSettings.None : PropertyMetadataSettings.AffectsLayout; - -var weakEvents: typeof weakEventListenerModule; -function ensureWeakEvents() { - if (!weakEvents) { - weakEvents = require("ui/core/weak-event-listener"); - } -} - -const textProperty = new Property("text", "Button", new proxy.PropertyMetadata("", AffectsLayout)); -const formattedTextProperty = new Property("formattedText", "Button", new proxy.PropertyMetadata("", AffectsLayout)); -const textWrapProperty = new Property("textWrap", "Button", new proxy.PropertyMetadata(false, AffectsLayout)); - -function onTextPropertyChanged(data: PropertyChangeData) { - var button =