mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
Layouts are now implemented natively for Android.
This commit is contained in:
@@ -527,6 +527,62 @@
|
||||
<TypeScriptCompile Include="ui\html-view\html-view.android.ts" />
|
||||
<TypeScriptCompile Include="ui\html-view\html-view.d.ts" />
|
||||
<TypeScriptCompile Include="ui\html-view\html-view.ios.ts" />
|
||||
<TypeScriptCompile Include="org.nativescript.widgets.d.ts" />
|
||||
<TypeScriptCompile Include="ui\layouts\absolute-layout\absolute-layout-common.ts">
|
||||
<DependentUpon>absolute-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\absolute-layout\absolute-layout.ios.ts">
|
||||
<DependentUpon>absolute-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\absolute-layout\absolute-layout.android.ts">
|
||||
<DependentUpon>absolute-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\dock-layout\dock-layout.ios.ts">
|
||||
<DependentUpon>dock-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\dock-layout\dock-layout.android.ts">
|
||||
<DependentUpon>dock-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\dock-layout\dock-layout-common.ts">
|
||||
<DependentUpon>dock-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\grid-layout\grid-layout-common.ts">
|
||||
<DependentUpon>grid-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\grid-layout\grid-layout.android.ts">
|
||||
<DependentUpon>grid-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\grid-layout\grid-layout.ios.ts">
|
||||
<DependentUpon>grid-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\layout.ios.ts">
|
||||
<DependentUpon>layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\layout.android.ts">
|
||||
<DependentUpon>layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\layout-base.ts">
|
||||
<DependentUpon>layout-base.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\layout-base.d.ts" />
|
||||
<TypeScriptCompile Include="ui\layouts\stack-layout\stack-layout.ios.ts">
|
||||
<DependentUpon>stack-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\stack-layout\stack-layout.android.ts">
|
||||
<DependentUpon>stack-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\stack-layout\stack-layout-common.ts">
|
||||
<DependentUpon>stack-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\wrap-layout\wrap-layout-common.ts">
|
||||
<DependentUpon>wrap-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\wrap-layout\wrap-layout.android.ts">
|
||||
<DependentUpon>wrap-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\wrap-layout\wrap-layout.ios.ts">
|
||||
<DependentUpon>wrap-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\repeater\repeater.ts">
|
||||
<DependentUpon>repeater.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
@@ -588,26 +644,11 @@
|
||||
<TypeScriptCompile Include="ui\image-cache\image-cache.ios.ts">
|
||||
<DependentUpon>image-cache.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\absolute-layout\absolute-layout.ts">
|
||||
<DependentUpon>absolute-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\dock-layout\dock-layout.ts">
|
||||
<DependentUpon>dock-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\grid-layout\grid-layout.ts">
|
||||
<DependentUpon>grid-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\layout.ts">
|
||||
<DependentUpon>layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\layout.d.ts" />
|
||||
<TypeScriptCompile Include="ui\layouts\absolute-layout\absolute-layout.d.ts" />
|
||||
<TypeScriptCompile Include="ui\layouts\wrap-layout\wrap-layout.d.ts" />
|
||||
<TypeScriptCompile Include="ui\layouts\grid-layout\grid-layout.d.ts" />
|
||||
<TypeScriptCompile Include="ui\layouts\dock-layout\dock-layout.d.ts" />
|
||||
<TypeScriptCompile Include="ui\layouts\stack-layout\stack-layout.ts">
|
||||
<DependentUpon>stack-layout.d.ts</DependentUpon>
|
||||
</TypeScriptCompile>
|
||||
<TypeScriptCompile Include="ui\layouts\stack-layout\stack-layout.d.ts" />
|
||||
<TypeScriptCompile Include="ui\layouts\wrap-layout\wrap-layout.ts">
|
||||
<DependentUpon>wrap-layout.d.ts</DependentUpon>
|
||||
|
||||
@@ -3,12 +3,9 @@ import slider = require("ui/slider");
|
||||
import imageSource = require("image-source");
|
||||
import gridModule = require("ui/layouts/grid-layout");
|
||||
import enums = require("ui/enums");
|
||||
|
||||
import img = require("ui/image");
|
||||
var Image = img.Image;
|
||||
export function createPage() {
|
||||
var StackLayout = require("ui/layouts/stack-layout").StackLayout;
|
||||
var Image = require("ui/image").Image;
|
||||
|
||||
var stack = new StackLayout();
|
||||
var grid = new gridModule.GridLayout();
|
||||
|
||||
grid.addColumn(new gridModule.ItemSpec(1, gridModule.GridUnitType.auto));
|
||||
@@ -17,24 +14,16 @@ export function createPage() {
|
||||
grid.addRow(new gridModule.ItemSpec(1, gridModule.GridUnitType.auto));
|
||||
grid.addRow(new gridModule.ItemSpec(1, gridModule.GridUnitType.star));
|
||||
|
||||
var sldr = new slider.Slider();
|
||||
gridModule.GridLayout.setColumnSpan(sldr, 2);
|
||||
sldr.maxValue = 500;
|
||||
|
||||
stack.addChild(sldr);
|
||||
stack.addChild(grid);
|
||||
|
||||
var image = new Image();
|
||||
image.stretch = enums.Stretch.fill;
|
||||
image.verticalAlignment = 2;
|
||||
image.horizontalAlignment = 1;
|
||||
image.verticalAlignment = enums.VerticalAlignment.bottom;
|
||||
image.horizontalAlignment = enums.HorizontalAlignment.center;
|
||||
|
||||
image.source = imageSource.fromFile(__dirname + "test.png");
|
||||
image.imageSource = imageSource.fromFile(__dirname + "/test.png");
|
||||
grid.addChild(image);
|
||||
|
||||
var page = new pages.Page();
|
||||
page.content = stack;
|
||||
page.content = grid;
|
||||
page.css = "GridLayout { background-color: pink } image { background-color: green }";
|
||||
return page;
|
||||
}
|
||||
//export var Page = page;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import observable = require("data/observable");
|
||||
import enums = require("ui/enums");
|
||||
import view = require("ui/core/view");
|
||||
import layouts = require("ui/layouts/layout");
|
||||
import layouts = require("ui/layouts/layout-base");
|
||||
|
||||
export class ViewModel extends observable.Observable {
|
||||
|
||||
@@ -67,7 +67,7 @@ export class ViewModel extends observable.Observable {
|
||||
|
||||
public onVisibile(args: { eventName: string, object: any }): void {
|
||||
var view: view.View = <view.View>args.object;
|
||||
var layout = <layouts.Layout>view.parent;
|
||||
var layout = <layouts.LayoutBase>view.parent;
|
||||
|
||||
var child = layout.getViewById("collapse");
|
||||
child.visibility = enums.Visibility.visible;
|
||||
|
||||
@@ -47,6 +47,7 @@ export class ContentView extends view.CustomLayoutView implements definition.Con
|
||||
}
|
||||
}
|
||||
|
||||
// This method won't be called in Android because we use the native android layout.
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
var result = view.View.measureChild(this, this.content, widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
@@ -66,6 +67,7 @@ export class ContentView extends view.CustomLayoutView implements definition.Con
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
|
||||
// This method won't be called in Android because we use the native android layout.
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
view.View.layoutChild(this, this.content, 0, 0, right - left, bottom - top);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ export class PropertyMetadata implements definition.PropertyMetadata {
|
||||
equalityComparer?: definition.PropertyEqualityComparer) {
|
||||
this._defaultValue = defaultValue;
|
||||
this._options = options;
|
||||
if (types.isUndefined(this._options)) {
|
||||
if (types.isNullOrUndefined(this._options)) {
|
||||
this._options = PropertyMetadataSettings.None;
|
||||
}
|
||||
this._onChanged = onChanged;
|
||||
|
||||
@@ -128,6 +128,7 @@ export class View extends proxy.ProxyObject implements definition.View {
|
||||
private _requestedVisualState: string;
|
||||
private _isLoaded: boolean;
|
||||
private _isLayoutValid: boolean = false;
|
||||
|
||||
public _domId: number;
|
||||
public _isAddedToNativeVisualTree = false;
|
||||
|
||||
@@ -293,41 +294,6 @@ export class View extends proxy.ProxyObject implements definition.View {
|
||||
this.style.marginBottom = value;
|
||||
}
|
||||
|
||||
get padding(): string {
|
||||
return this.style.padding;
|
||||
}
|
||||
set padding(value: string) {
|
||||
this.style.padding = value;
|
||||
}
|
||||
|
||||
get paddingLeft(): number {
|
||||
return this.style.paddingLeft;
|
||||
}
|
||||
set paddingLeft(value: number) {
|
||||
this.style.paddingLeft = value;
|
||||
}
|
||||
|
||||
get paddingTop(): number {
|
||||
return this.style.paddingTop;
|
||||
}
|
||||
set paddingTop(value: number) {
|
||||
this.style.paddingTop = value;
|
||||
}
|
||||
|
||||
get paddingRight(): number {
|
||||
return this.style.paddingRight;
|
||||
}
|
||||
set paddingRight(value: number) {
|
||||
this.style.paddingRight = value;
|
||||
}
|
||||
|
||||
get paddingBottom(): number {
|
||||
return this.style.paddingBottom;
|
||||
}
|
||||
set paddingBottom(value: number) {
|
||||
this.style.paddingBottom = value;
|
||||
}
|
||||
|
||||
get horizontalAlignment(): string {
|
||||
return this.style.horizontalAlignment;
|
||||
}
|
||||
@@ -510,11 +476,11 @@ export class View extends proxy.ProxyObject implements definition.View {
|
||||
}
|
||||
|
||||
public getMeasuredWidth(): number {
|
||||
return this._measuredWidth;
|
||||
return this._measuredWidth & utils.layout.MEASURED_SIZE_MASK;
|
||||
}
|
||||
|
||||
public getMeasuredHeight(): number {
|
||||
return this._measuredHeight;
|
||||
return this._measuredHeight & utils.layout.MEASURED_SIZE_MASK;
|
||||
}
|
||||
|
||||
public setMeasuredDimension(measuredWidth: number, measuredHeight: number): void {
|
||||
|
||||
@@ -32,16 +32,13 @@ function onIsUserInteractionEnabledPropertyChanged(data: dependencyObservable.Pr
|
||||
(<proxy.PropertyMetadata>viewCommon.View.isUserInteractionEnabledProperty.metadata).onSetNativeValue = onIsUserInteractionEnabledPropertyChanged;
|
||||
|
||||
export var NativeViewGroup = (<any>android.view.ViewGroup).extend({
|
||||
get owner() {
|
||||
return this[OWNER];
|
||||
},
|
||||
onMeasure: function (widthMeasureSpec, heightMeasureSpec) {
|
||||
var owner: viewDefinition.View = this.owner;
|
||||
var owner: viewDefinition.View = this[OWNER];
|
||||
owner.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
this.setMeasuredDimension(owner.getMeasuredWidth(), owner.getMeasuredHeight());
|
||||
},
|
||||
onLayout: function (changed: boolean, left: number, top: number, right: number, bottom: number): void {
|
||||
var owner: viewDefinition.View = this.owner;
|
||||
var owner: viewDefinition.View = this[OWNER];
|
||||
owner.onLayout(left, top, right, bottom);
|
||||
}
|
||||
});
|
||||
@@ -239,6 +236,14 @@ export class View extends viewCommon.View {
|
||||
return this.android;
|
||||
}
|
||||
|
||||
get isLayoutValid(): boolean {
|
||||
if (this._nativeView) {
|
||||
return !this._nativeView.isLayoutRequested();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public layoutNativeView(left: number, top: number, right: number, bottom: number): void {
|
||||
if (this._nativeView) {
|
||||
this._nativeView.layout(left, top, right, bottom);
|
||||
@@ -287,8 +292,8 @@ export class View extends viewCommon.View {
|
||||
}
|
||||
|
||||
public focus(): boolean {
|
||||
if (this.android) {
|
||||
return this.android.requestFocus();
|
||||
if (this._nativeView) {
|
||||
return this._nativeView.requestFocus();
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -328,15 +333,9 @@ export class CustomLayoutView extends View implements viewDefinition.CustomLayou
|
||||
}
|
||||
|
||||
public _createUI() {
|
||||
this._viewGroup = new NativeViewGroup(this._context);
|
||||
this._viewGroup[OWNER] = this;
|
||||
this._viewGroup = new org.nativescript.widgets.ContentLayout(this._context);
|
||||
}
|
||||
|
||||
//public _onDetached(force?: boolean) {
|
||||
// delete this._viewGroup[OWNER];
|
||||
// super._onDetached(force);
|
||||
//}
|
||||
|
||||
public _addViewToNativeVisualTree(child: View): boolean {
|
||||
super._addViewToNativeVisualTree(child);
|
||||
|
||||
@@ -356,46 +355,4 @@ export class CustomLayoutView extends View implements viewDefinition.CustomLayou
|
||||
trace.notifyEvent(child, "childInLayoutRemovedFromNativeVisualTree");
|
||||
}
|
||||
}
|
||||
|
||||
public measure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
this._setCurrentMeasureSpecs(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
var view = this._nativeView;
|
||||
if (view) {
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
trace.write(this + " :measure: " + utils.layout.getMode(widthMode) + " " + width + ", " + utils.layout.getMode(heightMode) + " " + height, trace.categories.Layout);
|
||||
view.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
|
||||
public layout(left: number, top: number, right: number, bottom: number): void {
|
||||
this._setCurrentLayoutBounds(left, top, right, bottom);
|
||||
|
||||
var view = this._nativeView;
|
||||
if (view) {
|
||||
this.layoutNativeView(left, top, right, bottom);
|
||||
trace.write(this + " :layout: " + left + ", " + top + ", " + (right - left) + ", " + (bottom - top), trace.categories.Layout);
|
||||
}
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
// Don't call super because it will trigger measure again.
|
||||
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
trace.write(this + " :onMeasure: " + utils.layout.getMode(widthMode) + " " + width + ", " + utils.layout.getMode(heightMode) + " " + height, trace.categories.Layout);
|
||||
}
|
||||
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
// Don't call super because it will trigger layout again.
|
||||
trace.write(this + " :onLayout: " + left + ", " + top + ", " + (right - left) + ", " + (bottom - top), trace.categories.Layout);
|
||||
}
|
||||
}
|
||||
25
ui/core/view.d.ts
vendored
25
ui/core/view.d.ts
vendored
@@ -205,31 +205,6 @@ declare module "ui/core/view" {
|
||||
*/
|
||||
marginBottom: number;
|
||||
|
||||
/**
|
||||
* Gets or sets padding style property.
|
||||
*/
|
||||
padding: string;
|
||||
|
||||
/**
|
||||
* Specify the left padding of this view.
|
||||
*/
|
||||
paddingLeft: number;
|
||||
|
||||
/**
|
||||
* Specify the top padding of this view.
|
||||
*/
|
||||
paddingTop: number;
|
||||
|
||||
/**
|
||||
* Specify the right padding of this view.
|
||||
*/
|
||||
paddingRight: number;
|
||||
|
||||
/**
|
||||
* Specify the bottom padding of this view.
|
||||
*/
|
||||
paddingBottom: number;
|
||||
|
||||
/**
|
||||
* Gets or sets the alignment of this view within its parent along the Horizontal axis.
|
||||
*/
|
||||
|
||||
@@ -85,13 +85,18 @@ export class View extends viewCommon.View {
|
||||
// For UILabel and UIImage.
|
||||
view.userInteractionEnabled = true;
|
||||
}
|
||||
|
||||
get isLayoutRequested(): boolean {
|
||||
return (this._privateFlags & PFLAG_FORCE_LAYOUT) === PFLAG_FORCE_LAYOUT;
|
||||
}
|
||||
|
||||
public requestLayout(): void {
|
||||
super.requestLayout();
|
||||
this._privateFlags |= PFLAG_FORCE_LAYOUT;
|
||||
|
||||
if (this.parent) {
|
||||
this.parent.requestLayout();
|
||||
var parent = <View>this.parent;
|
||||
if (parent && !parent.isLayoutRequested) {
|
||||
parent.requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +241,7 @@ export class CustomLayoutView extends View {
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
// Don't call super because it will trigger measure again.
|
||||
// Don't call super because it will set MeasureDimension. This method must be overriden and calculate its measuredDimensions.
|
||||
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
@@ -327,25 +327,6 @@ export class Frame extends view.CustomLayoutView implements definition.Frame {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
var result = view.View.measureChild(this, this.currentPage, widthMeasureSpec, utils.layout.makeMeasureSpec(height - this.navigationBarHeight, heightMode));
|
||||
|
||||
var widthAndState = view.View.resolveSizeAndState(result.measuredWidth, width, widthMode, 0);
|
||||
var heightAndState = view.View.resolveSizeAndState(result.measuredHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
view.View.layoutChild(this, this.currentPage, 0, this.navigationBarHeight, right - left, bottom - top);
|
||||
}
|
||||
|
||||
// We don't need to put Page as visual child. Don't call super.
|
||||
public _addViewToNativeVisualTree(child: view.View): boolean {
|
||||
return true;
|
||||
|
||||
@@ -373,8 +373,7 @@ var NativeActivity = {
|
||||
this.androidFrame.setActivity(this);
|
||||
|
||||
// Create and set content container.
|
||||
var root = new view.NativeViewGroup(this);
|
||||
root[OWNER] = this.frame;
|
||||
var root = new org.nativescript.widgets.ContentLayout(this);
|
||||
|
||||
this.androidFrame.rootViewGroup = root;
|
||||
this.androidFrame.rootViewGroup.setId(this.frame.containerViewId);
|
||||
|
||||
@@ -3,9 +3,7 @@ import view = require("ui/core/view");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import imageSource = require("image-source");
|
||||
import definition = require("ui/image");
|
||||
import trace = require("trace");
|
||||
import enums = require("ui/enums");
|
||||
import utils = require("utils/utils");
|
||||
import types = require("utils/types");
|
||||
|
||||
var SRC = "src";
|
||||
@@ -49,43 +47,18 @@ function onSrcPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
|
||||
export class Image extends view.View implements definition.Image {
|
||||
|
||||
public static srcProperty = new dependencyObservable.Property(
|
||||
SRC,
|
||||
IMAGE,
|
||||
new proxy.PropertyMetadata(
|
||||
undefined,
|
||||
dependencyObservable.PropertyMetadataSettings.None,
|
||||
onSrcPropertyChanged
|
||||
)
|
||||
);
|
||||
public static srcProperty = new dependencyObservable.Property(SRC, IMAGE,
|
||||
new proxy.PropertyMetadata(undefined, dependencyObservable.PropertyMetadataSettings.None, onSrcPropertyChanged));
|
||||
|
||||
public static imageSourceProperty = new dependencyObservable.Property(
|
||||
IMAGE_SOURCE,
|
||||
IMAGE,
|
||||
new proxy.PropertyMetadata(
|
||||
undefined,
|
||||
// None on purpose. for iOS we trigger it manually if needed. Android layout handles it.
|
||||
dependencyObservable.PropertyMetadataSettings.None
|
||||
)
|
||||
);
|
||||
// None on purpose. for iOS we trigger it manually if needed. Android layout handles it.
|
||||
public static imageSourceProperty = new dependencyObservable.Property(IMAGE_SOURCE, IMAGE,
|
||||
new proxy.PropertyMetadata(undefined, dependencyObservable.PropertyMetadataSettings.None));
|
||||
|
||||
public static isLoadingProperty = new dependencyObservable.Property(
|
||||
ISLOADING,
|
||||
IMAGE,
|
||||
new proxy.PropertyMetadata(
|
||||
false,
|
||||
dependencyObservable.PropertyMetadataSettings.None
|
||||
)
|
||||
);
|
||||
public static isLoadingProperty = new dependencyObservable.Property(ISLOADING, IMAGE,
|
||||
new proxy.PropertyMetadata(false, dependencyObservable.PropertyMetadataSettings.None));
|
||||
|
||||
public static stretchProperty = new dependencyObservable.Property(
|
||||
STRETCH,
|
||||
IMAGE,
|
||||
new proxy.PropertyMetadata(
|
||||
enums.Stretch.aspectFit,
|
||||
dependencyObservable.PropertyMetadataSettings.AffectsLayout
|
||||
)
|
||||
);
|
||||
public static stretchProperty = new dependencyObservable.Property(STRETCH, IMAGE,
|
||||
new proxy.PropertyMetadata(enums.Stretch.aspectFit, dependencyObservable.PropertyMetadataSettings.AffectsLayout));
|
||||
|
||||
constructor(options?: definition.Options) {
|
||||
super(options);
|
||||
@@ -119,75 +92,4 @@ export class Image extends view.View implements definition.Image {
|
||||
public _setNativeImage(nativeImage: any) {
|
||||
//
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
|
||||
// We don't call super because we measure native view with specific size.
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
trace.write(this + " :onMeasure: " + utils.layout.getMode(widthMode) + " " + width + ", " + utils.layout.getMode(heightMode) + " " + height, trace.categories.Layout);
|
||||
|
||||
var nativeWidth = this.imageSource ? this.imageSource.width : 0;
|
||||
var nativeHeight = this.imageSource ? this.imageSource.height : 0;
|
||||
|
||||
var measureWidth = Math.max(nativeWidth, this.minWidth);
|
||||
var measureHeight = Math.max(nativeHeight, this.minHeight);
|
||||
|
||||
var finiteWidth: boolean = widthMode !== utils.layout.UNSPECIFIED;
|
||||
var finiteHeight: boolean = heightMode !== utils.layout.UNSPECIFIED;
|
||||
|
||||
if (nativeWidth !== 0 && nativeHeight !== 0 && (finiteWidth || finiteHeight)) {
|
||||
var scale = Image.computeScaleFactor(width, height, finiteWidth, finiteHeight, nativeWidth, nativeHeight, this.stretch);
|
||||
var resultW = Math.floor(nativeWidth * scale.width);
|
||||
var resultH = Math.floor(nativeHeight * scale.height);
|
||||
|
||||
measureWidth = finiteWidth ? Math.min(resultW, width) : resultW;
|
||||
measureHeight = finiteHeight ? Math.min(resultH, height) : resultH;
|
||||
|
||||
trace.write("Image stretch: " + this.stretch +
|
||||
", nativeWidth: " + nativeWidth +
|
||||
", nativeHeight: " + nativeHeight, trace.categories.Layout);
|
||||
}
|
||||
|
||||
var widthAndState = view.View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
var heightAndState = view.View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
|
||||
private static computeScaleFactor(measureWidth: number, measureHeight: number, widthIsFinite: boolean, heightIsFinite: boolean, nativeWidth: number, nativeHeight: number, imageStretch: string): { width: number; height: number } {
|
||||
var scaleW = 1;
|
||||
var scaleH = 1;
|
||||
|
||||
if ((imageStretch === enums.Stretch.aspectFill || imageStretch === enums.Stretch.aspectFit || imageStretch === enums.Stretch.fill) &&
|
||||
(widthIsFinite || heightIsFinite)) {
|
||||
|
||||
scaleW = (nativeWidth > 0) ? measureWidth / nativeWidth : 0;
|
||||
scaleH = (nativeHeight > 0) ? measureHeight / nativeHeight : 0;
|
||||
|
||||
if (!widthIsFinite) {
|
||||
scaleW = scaleH;
|
||||
}
|
||||
else if (!heightIsFinite) {
|
||||
scaleH = scaleW;
|
||||
}
|
||||
else {
|
||||
// No infinite dimensions.
|
||||
switch (imageStretch) {
|
||||
case enums.Stretch.aspectFit:
|
||||
scaleH = scaleW < scaleH ? scaleW : scaleH;
|
||||
scaleW = scaleH;
|
||||
break;
|
||||
case enums.Stretch.aspectFill:
|
||||
scaleH = scaleW > scaleH ? scaleW : scaleH;
|
||||
scaleW = scaleH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return { width: scaleW, height: scaleH };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,14 +42,14 @@ function onImageSourcePropertyChanged(data: dependencyObservable.PropertyChangeD
|
||||
(<proxy.PropertyMetadata>imageCommon.Image.stretchProperty.metadata).onSetNativeValue = onStretchPropertyChanged;
|
||||
|
||||
export class Image extends imageCommon.Image {
|
||||
private _android: android.widget.ImageView;
|
||||
private _android: org.nativescript.widgets.ImageView;
|
||||
|
||||
get android(): android.widget.ImageView {
|
||||
get android(): org.nativescript.widgets.ImageView {
|
||||
return this._android;
|
||||
}
|
||||
|
||||
public _createUI() {
|
||||
this._android = new android.widget.ImageView(this._context);
|
||||
this._android = new org.nativescript.widgets.ImageView(this._context);
|
||||
}
|
||||
|
||||
public _setNativeImage(nativeImage: any) {
|
||||
|
||||
@@ -3,6 +3,9 @@ import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import definition = require("ui/image");
|
||||
import enums = require("ui/enums");
|
||||
import utils = require("utils/utils");
|
||||
import trace = require("trace");
|
||||
import view = require("ui/core/view");
|
||||
|
||||
global.moduleMerge(imageCommon, exports);
|
||||
|
||||
@@ -59,4 +62,75 @@ export class Image extends imageCommon.Image {
|
||||
this.requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
|
||||
// We don't call super because we measure native view with specific size.
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
trace.write(this + " :onMeasure: " + utils.layout.getMode(widthMode) + " " + width + ", " + utils.layout.getMode(heightMode) + " " + height, trace.categories.Layout);
|
||||
|
||||
var nativeWidth = this.imageSource ? this.imageSource.width : 0;
|
||||
var nativeHeight = this.imageSource ? this.imageSource.height : 0;
|
||||
|
||||
var measureWidth = Math.max(nativeWidth, this.minWidth);
|
||||
var measureHeight = Math.max(nativeHeight, this.minHeight);
|
||||
|
||||
var finiteWidth: boolean = widthMode !== utils.layout.UNSPECIFIED;
|
||||
var finiteHeight: boolean = heightMode !== utils.layout.UNSPECIFIED;
|
||||
|
||||
if (nativeWidth !== 0 && nativeHeight !== 0 && (finiteWidth || finiteHeight)) {
|
||||
var scale = Image.computeScaleFactor(width, height, finiteWidth, finiteHeight, nativeWidth, nativeHeight, this.stretch);
|
||||
var resultW = Math.floor(nativeWidth * scale.width);
|
||||
var resultH = Math.floor(nativeHeight * scale.height);
|
||||
|
||||
measureWidth = finiteWidth ? Math.min(resultW, width) : resultW;
|
||||
measureHeight = finiteHeight ? Math.min(resultH, height) : resultH;
|
||||
|
||||
trace.write("Image stretch: " + this.stretch +
|
||||
", nativeWidth: " + nativeWidth +
|
||||
", nativeHeight: " + nativeHeight, trace.categories.Layout);
|
||||
}
|
||||
|
||||
var widthAndState = view.View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
var heightAndState = view.View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
|
||||
private static computeScaleFactor(measureWidth: number, measureHeight: number, widthIsFinite: boolean, heightIsFinite: boolean, nativeWidth: number, nativeHeight: number, imageStretch: string): { width: number; height: number } {
|
||||
var scaleW = 1;
|
||||
var scaleH = 1;
|
||||
|
||||
if ((imageStretch === enums.Stretch.aspectFill || imageStretch === enums.Stretch.aspectFit || imageStretch === enums.Stretch.fill) &&
|
||||
(widthIsFinite || heightIsFinite)) {
|
||||
|
||||
scaleW = (nativeWidth > 0) ? measureWidth / nativeWidth : 0;
|
||||
scaleH = (nativeHeight > 0) ? measureHeight / nativeHeight : 0;
|
||||
|
||||
if (!widthIsFinite) {
|
||||
scaleW = scaleH;
|
||||
}
|
||||
else if (!heightIsFinite) {
|
||||
scaleH = scaleW;
|
||||
}
|
||||
else {
|
||||
// No infinite dimensions.
|
||||
switch (imageStretch) {
|
||||
case enums.Stretch.aspectFit:
|
||||
scaleH = scaleW < scaleH ? scaleW : scaleH;
|
||||
scaleW = scaleH;
|
||||
break;
|
||||
case enums.Stretch.aspectFill:
|
||||
scaleH = scaleW > scaleH ? scaleW : scaleH;
|
||||
scaleW = scaleH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return { width: scaleW, height: scaleH };
|
||||
}
|
||||
}
|
||||
69
ui/layouts/absolute-layout/absolute-layout-common.ts
Normal file
69
ui/layouts/absolute-layout/absolute-layout-common.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import layouts = require("ui/layouts/layout-base");
|
||||
import definition = require("ui/layouts/absolute-layout");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import view = require("ui/core/view");
|
||||
import proxy = require("ui/core/proxy");
|
||||
|
||||
function validateArgs(element: view.View): view.View {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
export class AbsoluteLayout extends layouts.LayoutBase implements definition.AbsoluteLayout {
|
||||
|
||||
private static isValid(value: number): boolean {
|
||||
return isFinite(value);
|
||||
}
|
||||
|
||||
private static onLeftPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
var uiView = data.object;
|
||||
if (uiView instanceof view.View) {
|
||||
var layout = uiView.parent;
|
||||
if (layout instanceof AbsoluteLayout) {
|
||||
layout.onLeftChanged(uiView, data.oldValue, data.newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static onTopPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
var uiView = data.object;
|
||||
if (uiView instanceof view.View) {
|
||||
var layout = uiView.parent;
|
||||
if (layout instanceof AbsoluteLayout) {
|
||||
layout.onTopChanged(uiView, data.oldValue, data.newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static leftProperty = new dependencyObservable.Property("left", "AbsoluteLayout",
|
||||
new proxy.PropertyMetadata(0, undefined, AbsoluteLayout.onLeftPropertyChanged, AbsoluteLayout.isValid));
|
||||
|
||||
public static topProperty = new dependencyObservable.Property("top", "AbsoluteLayout",
|
||||
new proxy.PropertyMetadata(0, undefined, AbsoluteLayout.onTopPropertyChanged, AbsoluteLayout.isValid));
|
||||
|
||||
public static getLeft(element: view.View): number {
|
||||
return validateArgs(element)._getValue(AbsoluteLayout.leftProperty);
|
||||
}
|
||||
|
||||
public static setLeft(element: view.View, value: number): void {
|
||||
validateArgs(element)._setValue(AbsoluteLayout.leftProperty, value);
|
||||
}
|
||||
|
||||
public static getTop(element: view.View): number {
|
||||
return validateArgs(element)._getValue(AbsoluteLayout.topProperty);
|
||||
}
|
||||
|
||||
public static setTop(element: view.View, value: number): void {
|
||||
validateArgs(element)._setValue(AbsoluteLayout.topProperty, value);
|
||||
}
|
||||
|
||||
protected onLeftChanged(view: view.View, oldValue: number, newValue: number) {
|
||||
//
|
||||
}
|
||||
|
||||
protected onTopChanged(view: view.View, oldValue: number, newValue: number) {
|
||||
//
|
||||
}
|
||||
}
|
||||
52
ui/layouts/absolute-layout/absolute-layout.android.ts
Normal file
52
ui/layouts/absolute-layout/absolute-layout.android.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import utils = require("utils/utils");
|
||||
import view = require("ui/core/view");
|
||||
import common = require("ui/layouts/absolute-layout/absolute-layout-common");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import proxy = require("ui/core/proxy");
|
||||
|
||||
// merge the exports of the common file with the exports of this file
|
||||
declare var exports;
|
||||
require("utils/module-merge").merge(common, exports);
|
||||
|
||||
function setNativeProperty(data: dependencyObservable.PropertyChangeData, setter: (lp: org.nativescript.widgets.CommonLayoutParams) => void) {
|
||||
|
||||
var uiView = data.object;
|
||||
if (uiView instanceof view.View) {
|
||||
var nativeView: android.view.View = uiView._nativeView;
|
||||
|
||||
var lp = <org.nativescript.widgets.CommonLayoutParams>nativeView.getLayoutParams();
|
||||
if (!(lp instanceof org.nativescript.widgets.CommonLayoutParams)) {
|
||||
lp = new org.nativescript.widgets.CommonLayoutParams();
|
||||
}
|
||||
setter(lp);
|
||||
nativeView.setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
|
||||
function setNativeLeftProperty(data: dependencyObservable.PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.left = data.newValue * utils.layout.getDisplayDensity(); });
|
||||
}
|
||||
|
||||
function setNativeTopProperty(data: dependencyObservable.PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.top = data.newValue * utils.layout.getDisplayDensity(); });
|
||||
}
|
||||
|
||||
(<proxy.PropertyMetadata>common.AbsoluteLayout.leftProperty.metadata).onSetNativeValue = setNativeLeftProperty;
|
||||
(<proxy.PropertyMetadata>common.AbsoluteLayout.topProperty.metadata).onSetNativeValue = setNativeTopProperty;
|
||||
|
||||
export class AbsoluteLayout extends common.AbsoluteLayout {
|
||||
|
||||
private _layout: org.nativescript.widgets.AbsoluteLayout;
|
||||
|
||||
get android(): org.nativescript.widgets.AbsoluteLayout {
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
get _nativeView(): org.nativescript.widgets.AbsoluteLayout {
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
public _createUI() {
|
||||
this._layout = new org.nativescript.widgets.AbsoluteLayout(this._context);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
declare module "ui/layouts/absolute-layout" {
|
||||
import layout = require("ui/layouts/layout");
|
||||
import layout = require("ui/layouts/layout-base");
|
||||
import view = require("ui/core/view");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
|
||||
/**
|
||||
* A layout that lets you specify exact locations (left/top coordinates) of its children.
|
||||
*/
|
||||
class AbsoluteLayout extends layout.Layout {
|
||||
class AbsoluteLayout extends layout.LayoutBase {
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the left property.
|
||||
|
||||
@@ -1,56 +1,19 @@
|
||||
import layouts = require("ui/layouts/layout");
|
||||
import definition = require("ui/layouts/absolute-layout");
|
||||
import utils = require("utils/utils");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import utils = require("utils/utils");
|
||||
import view = require("ui/core/view");
|
||||
import numberUtils = require("utils/number-utils");
|
||||
import common = require("ui/layouts/absolute-layout/absolute-layout-common");
|
||||
|
||||
function onPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
var uiView = data.object;
|
||||
if (uiView instanceof view.View) {
|
||||
var layout = uiView.parent;
|
||||
if (layout instanceof AbsoluteLayout) {
|
||||
layout.requestLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
// merge the exports of the common file with the exports of this file
|
||||
declare var exports;
|
||||
require("utils/module-merge").merge(common, exports);
|
||||
|
||||
export class AbsoluteLayout extends layouts.Layout implements definition.AbsoluteLayout {
|
||||
export class AbsoluteLayout extends common.AbsoluteLayout {
|
||||
|
||||
public static leftProperty = new dependencyObservable.Property("left", "AbsoluteLayout",
|
||||
new dependencyObservable.PropertyMetadata(0, undefined, onPropertyChanged, numberUtils.isFiniteNumber));
|
||||
|
||||
public static topProperty = new dependencyObservable.Property("top", "AbsoluteLayout",
|
||||
new dependencyObservable.PropertyMetadata(0, undefined, onPropertyChanged, numberUtils.isFiniteNumber));
|
||||
|
||||
public static getLeft(element: view.View): number {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
|
||||
return element._getValue(AbsoluteLayout.leftProperty);
|
||||
protected onLeftChanged(view: view.View, oldValue: number, newValue: number) {
|
||||
this.requestLayout();
|
||||
}
|
||||
|
||||
public static setLeft(element: view.View, value: number): void {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
element._setValue(AbsoluteLayout.leftProperty, value);
|
||||
}
|
||||
|
||||
public static getTop(element: view.View): number {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
|
||||
return element._getValue(AbsoluteLayout.topProperty);
|
||||
}
|
||||
|
||||
public static setTop(element: view.View, value: number): void {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
element._setValue(AbsoluteLayout.topProperty, value);
|
||||
protected onTopChanged(view: view.View, oldValue: number, newValue: number) {
|
||||
this.requestLayout();
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
58
ui/layouts/dock-layout/dock-layout-common.ts
Normal file
58
ui/layouts/dock-layout/dock-layout-common.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import layouts = require("ui/layouts/layout-base");
|
||||
import definition = require("ui/layouts/dock-layout");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import view = require("ui/core/view");
|
||||
import enums = require("ui/enums");
|
||||
import proxy = require("ui/core/proxy");
|
||||
|
||||
// on Android we explicitly set propertySettings to None because android will invalidate its layout (skip unnecessary native call).
|
||||
var AffectsLayout = global.android ? dependencyObservable.PropertyMetadataSettings.None : dependencyObservable.PropertyMetadataSettings.AffectsLayout;
|
||||
|
||||
function isDockValid(value: any): boolean {
|
||||
return value === enums.Dock.left || value === enums.Dock.top || value === enums.Dock.right || value === enums.Dock.bottom;
|
||||
}
|
||||
|
||||
function validateArgs(element: view.View): view.View {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
export class DockLayout extends layouts.LayoutBase implements definition.DockLayout {
|
||||
|
||||
private static onDockPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
var uiView = data.object;
|
||||
if (uiView instanceof view.View) {
|
||||
var layout = uiView.parent;
|
||||
if (layout instanceof DockLayout) {
|
||||
layout.onDockChanged(uiView, data.oldValue, data.newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static dockProperty = new dependencyObservable.Property(
|
||||
"dock", "DockLayout", new proxy.PropertyMetadata(enums.Dock.left, undefined, DockLayout.onDockPropertyChanged, isDockValid));
|
||||
|
||||
public static stretchLastChildProperty = new dependencyObservable.Property(
|
||||
"stretchLastChild", "DockLayout", new proxy.PropertyMetadata(true, AffectsLayout));
|
||||
|
||||
public static getDock(element: view.View): string {
|
||||
return validateArgs(element)._getValue(DockLayout.dockProperty);
|
||||
}
|
||||
|
||||
public static setDock(element: view.View, value: string): void {
|
||||
validateArgs(element)._setValue(DockLayout.dockProperty, value);
|
||||
}
|
||||
|
||||
get stretchLastChild(): boolean {
|
||||
return this._getValue(DockLayout.stretchLastChildProperty);
|
||||
}
|
||||
set stretchLastChild(value: boolean) {
|
||||
this._setValue(DockLayout.stretchLastChildProperty, value);
|
||||
}
|
||||
|
||||
protected onDockChanged(view: view.View, oldValue: number, newValue: number) {
|
||||
//
|
||||
}
|
||||
}
|
||||
69
ui/layouts/dock-layout/dock-layout.android.ts
Normal file
69
ui/layouts/dock-layout/dock-layout.android.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import definition = require("ui/layouts/dock-layout");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import view = require("ui/core/view");
|
||||
import enums = require("ui/enums");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import common = require("ui/layouts/dock-layout/dock-layout-common");
|
||||
|
||||
// merge the exports of the common file with the exports of this file
|
||||
declare var exports;
|
||||
require("utils/module-merge").merge(common, exports);
|
||||
|
||||
function setNativeDockProperty(data: dependencyObservable.PropertyChangeData) {
|
||||
|
||||
var uiView = data.object;
|
||||
if (uiView instanceof view.View) {
|
||||
var nativeView: android.view.View = uiView._nativeView;
|
||||
|
||||
var lp = <org.nativescript.widgets.CommonLayoutParams>nativeView.getLayoutParams();
|
||||
if (!(lp instanceof org.nativescript.widgets.CommonLayoutParams)) {
|
||||
lp = new org.nativescript.widgets.CommonLayoutParams();
|
||||
}
|
||||
|
||||
switch (data.newValue) {
|
||||
case enums.Dock.left:
|
||||
lp.dock = org.nativescript.widgets.Dock.left;
|
||||
break;
|
||||
case enums.Dock.top:
|
||||
lp.dock = org.nativescript.widgets.Dock.top;
|
||||
break;
|
||||
case enums.Dock.right:
|
||||
lp.dock = org.nativescript.widgets.Dock.right;
|
||||
break;
|
||||
case enums.Dock.bottom:
|
||||
lp.dock = org.nativescript.widgets.Dock.bottom;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid dock value: " + data.newValue + " on element: " + uiView);
|
||||
}
|
||||
|
||||
nativeView.setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
|
||||
(<proxy.PropertyMetadata>common.DockLayout.dockProperty.metadata).onSetNativeValue = setNativeDockProperty;
|
||||
|
||||
export class DockLayout extends common.DockLayout {
|
||||
|
||||
static setNativeStretchLastChildProperty(data: dependencyObservable.PropertyChangeData) {
|
||||
var dockLayout = <DockLayout>data.object;
|
||||
var nativeView = dockLayout._nativeView;
|
||||
nativeView.setStretchLastChild(data.newValue);
|
||||
}
|
||||
|
||||
private _layout: org.nativescript.widgets.DockLayout;
|
||||
|
||||
get android(): org.nativescript.widgets.DockLayout {
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
get _nativeView(): org.nativescript.widgets.DockLayout {
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
public _createUI() {
|
||||
this._layout = new org.nativescript.widgets.DockLayout(this._context);
|
||||
}
|
||||
}
|
||||
|
||||
(<proxy.PropertyMetadata>common.DockLayout.stretchLastChildProperty.metadata).onSetNativeValue = DockLayout.setNativeStretchLastChildProperty;
|
||||
4
ui/layouts/dock-layout/dock-layout.d.ts
vendored
4
ui/layouts/dock-layout/dock-layout.d.ts
vendored
@@ -1,12 +1,12 @@
|
||||
declare module "ui/layouts/dock-layout" {
|
||||
import view = require("ui/core/view");
|
||||
import layout = require("ui/layouts/layout");
|
||||
import layout = require("ui/layouts/layout-base");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
|
||||
/**
|
||||
* A Layout that arranges its children at its outer edges, and allows its last child to take up the remaining space.
|
||||
*/
|
||||
class DockLayout extends layout.Layout {
|
||||
class DockLayout extends layout.LayoutBase {
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the dock property.
|
||||
|
||||
@@ -1,53 +1,12 @@
|
||||
import layouts = require("ui/layouts/layout");
|
||||
import definition = require("ui/layouts/dock-layout");
|
||||
import utils = require("utils/utils");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import utils = require("utils/utils");
|
||||
import view = require("ui/core/view");
|
||||
import enums = require("ui/enums");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import common = require("ui/layouts/dock-layout/dock-layout-common");
|
||||
|
||||
function isDockValid(value: any): boolean {
|
||||
return value === enums.Dock.left || value === enums.Dock.top || value === enums.Dock.right || value === enums.Dock.bottom;
|
||||
}
|
||||
export class DockLayout extends common.DockLayout {
|
||||
|
||||
function onDockPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
var uiView = data.object;
|
||||
if (uiView instanceof view.View) {
|
||||
var layout = (<view.View>uiView).parent;
|
||||
if (layout instanceof DockLayout) {
|
||||
layout.requestLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DockLayout extends layouts.Layout implements definition.DockLayout {
|
||||
|
||||
public static dockProperty = new dependencyObservable.Property(
|
||||
"dock", "DockLayout", new dependencyObservable.PropertyMetadata(enums.Dock.left, undefined, onDockPropertyChanged, isDockValid));
|
||||
|
||||
public static stretchLastChildProperty = new dependencyObservable.Property(
|
||||
"stretchLastChild", "DockLayout", new proxy.PropertyMetadata(true, dependencyObservable.PropertyMetadataSettings.AffectsLayout));
|
||||
|
||||
public static getDock(element: view.View): string {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
|
||||
return element._getValue(DockLayout.dockProperty);
|
||||
}
|
||||
|
||||
public static setDock(element: view.View, value: string): void {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
element._setValue(DockLayout.dockProperty, value);
|
||||
}
|
||||
|
||||
get stretchLastChild(): boolean {
|
||||
return this._getValue(DockLayout.stretchLastChildProperty);
|
||||
}
|
||||
set stretchLastChild(value: boolean) {
|
||||
this._setValue(DockLayout.stretchLastChildProperty, value);
|
||||
protected onDockChanged(view: view.View, oldValue: number, newValue: number) {
|
||||
this.requestLayout();
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
370
ui/layouts/grid-layout/grid-layout-common.ts
Normal file
370
ui/layouts/grid-layout/grid-layout-common.ts
Normal file
@@ -0,0 +1,370 @@
|
||||
import layouts = require("ui/layouts/layout-base");
|
||||
import definition = require("ui/layouts/grid-layout");
|
||||
import utils = require("utils/utils");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import enums = require("ui/enums");
|
||||
import view = require("ui/core/view");
|
||||
import bindable = require("ui/core/bindable");
|
||||
import types = require("utils/types");
|
||||
import numberUtils = require("utils/number-utils");
|
||||
import proxy = require("ui/core/proxy");
|
||||
|
||||
function validateArgs(element: view.View): view.View {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
export module GridUnitType {
|
||||
export var auto: string = "auto";
|
||||
export var pixel: string = "pixel";
|
||||
export var star: string = "star";
|
||||
}
|
||||
|
||||
export class ItemSpec extends bindable.Bindable implements definition.ItemSpec {
|
||||
|
||||
private _value: number;
|
||||
private _unitType: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
if (arguments.length === 0) {
|
||||
this._value = 1;
|
||||
this._unitType = GridUnitType.star;
|
||||
|
||||
}
|
||||
else if (arguments.length === 2) {
|
||||
if (types.isNumber(arguments[0]) && types.isString(arguments[1])) {
|
||||
if (arguments[0] < 0 || (arguments[1] !== GridUnitType.auto && arguments[1] !== GridUnitType.star && arguments[1] !== GridUnitType.pixel)) {
|
||||
throw new Error("Invalid values.");
|
||||
}
|
||||
this._value = arguments[0];
|
||||
this._unitType = arguments[1];
|
||||
}
|
||||
else {
|
||||
throw new Error("Arguments must be number and string.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error("ItemSpec expects 0 or 2 arguments");
|
||||
}
|
||||
|
||||
this.index = -1;
|
||||
}
|
||||
|
||||
public owner: GridLayout;
|
||||
public index: number;
|
||||
public _actualLength: number = 0;
|
||||
|
||||
public get actualLength(): number {
|
||||
return this._actualLength;
|
||||
}
|
||||
public set actualLength(value: number) {
|
||||
throw new Error("actualLength is read-only property");
|
||||
}
|
||||
|
||||
public static equals(value1: ItemSpec, value2: ItemSpec): boolean {
|
||||
return (value1.gridUnitType === value2.gridUnitType) && (value1.value === value2.value) && (value1.owner === value2.owner) && (value1.index === value2.index);
|
||||
}
|
||||
|
||||
get gridUnitType(): string {
|
||||
return this._unitType;
|
||||
}
|
||||
|
||||
get isAbsolute(): boolean {
|
||||
return this._unitType === GridUnitType.pixel;
|
||||
}
|
||||
|
||||
get isAuto(): boolean {
|
||||
return this._unitType === GridUnitType.auto;
|
||||
}
|
||||
|
||||
get isStar(): boolean {
|
||||
return this._unitType === GridUnitType.star;
|
||||
}
|
||||
|
||||
get value(): number {
|
||||
return this._value;
|
||||
}
|
||||
}
|
||||
|
||||
export class GridLayout extends layouts.LayoutBase implements definition.GridLayout, view.ApplyXmlAttributes {
|
||||
private _rows: Array<ItemSpec> = new Array<ItemSpec>();
|
||||
private _cols: Array<ItemSpec> = new Array<ItemSpec>();
|
||||
protected _singleRow: ItemSpec = new ItemSpec();
|
||||
protected _singleColumn: ItemSpec = new ItemSpec();
|
||||
|
||||
public static columnProperty = new dependencyObservable.Property("Column", "GridLayout",
|
||||
new proxy.PropertyMetadata(0, dependencyObservable.PropertyMetadataSettings.None, GridLayout.onColumnPropertyChanged, numberUtils.notNegative));
|
||||
|
||||
public static columnSpanProperty = new dependencyObservable.Property("ColumnSpan", "GridLayout",
|
||||
new proxy.PropertyMetadata(1, dependencyObservable.PropertyMetadataSettings.None, GridLayout.onColumnSpanPropertyChanged, numberUtils.greaterThanZero));
|
||||
|
||||
public static rowProperty = new dependencyObservable.Property("Row", "GridLayout",
|
||||
new proxy.PropertyMetadata(0, dependencyObservable.PropertyMetadataSettings.None, GridLayout.onRowPropertyChanged, numberUtils.notNegative));
|
||||
|
||||
public static rowSpanProperty = new dependencyObservable.Property("RowSpan", "GridLayout",
|
||||
new proxy.PropertyMetadata(1, dependencyObservable.PropertyMetadataSettings.None, GridLayout.onRowSpanPropertyChanged, numberUtils.greaterThanZero));
|
||||
|
||||
public static getColumn(element: view.View): number {
|
||||
return validateArgs(element)._getValue(GridLayout.columnProperty);
|
||||
}
|
||||
|
||||
public static setColumn(element: view.View, value: number): void {
|
||||
validateArgs(element)._setValue(GridLayout.columnProperty, value);
|
||||
}
|
||||
|
||||
public static getColumnSpan(element: view.View): number {
|
||||
return validateArgs(element)._getValue(GridLayout.columnSpanProperty);
|
||||
}
|
||||
|
||||
public static setColumnSpan(element: view.View, value: number): void {
|
||||
validateArgs(element)._setValue(GridLayout.columnSpanProperty, value);
|
||||
}
|
||||
|
||||
public static getRow(element: view.View): number {
|
||||
return validateArgs(element)._getValue(GridLayout.rowProperty);
|
||||
}
|
||||
|
||||
public static setRow(element: view.View, value: number): void {
|
||||
validateArgs(element)._setValue(GridLayout.rowProperty, value);
|
||||
}
|
||||
|
||||
public static getRowSpan(element: view.View): number {
|
||||
return validateArgs(element)._getValue(GridLayout.rowSpanProperty);
|
||||
}
|
||||
|
||||
public static setRowSpan(element: view.View, value: number): void {
|
||||
validateArgs(element)._setValue(GridLayout.rowSpanProperty, value);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._singleRow.index = 0
|
||||
this._singleColumn.index = 0;
|
||||
}
|
||||
|
||||
public addRow(itemSpec: ItemSpec) {
|
||||
GridLayout.validateItemSpec(itemSpec);
|
||||
itemSpec.owner = this;
|
||||
this._rows.push(itemSpec);
|
||||
this.onRowAdded(itemSpec);
|
||||
}
|
||||
|
||||
public addColumn(itemSpec: ItemSpec) {
|
||||
GridLayout.validateItemSpec(itemSpec);
|
||||
itemSpec.owner = this;
|
||||
this._cols.push(itemSpec);
|
||||
this.onColumnAdded(itemSpec);
|
||||
}
|
||||
|
||||
public removeRow(itemSpec: ItemSpec): void {
|
||||
if (!itemSpec) {
|
||||
throw new Error("Value is null.");
|
||||
}
|
||||
|
||||
var index = this._rows.indexOf(itemSpec);
|
||||
if (itemSpec.owner !== this || index < 0) {
|
||||
throw new Error("Row is not child of this GridLayout");
|
||||
}
|
||||
|
||||
itemSpec.index = -1;
|
||||
this._rows.splice(index, 1);
|
||||
this.onRowRemoved(itemSpec, index);
|
||||
}
|
||||
|
||||
public removeColumn(itemSpec: ItemSpec): void {
|
||||
if (!itemSpec) {
|
||||
throw new Error("Value is null.");
|
||||
}
|
||||
|
||||
var index = this._cols.indexOf(itemSpec);
|
||||
if (itemSpec.owner !== this || index < 0) {
|
||||
throw new Error("Column is not child of this GridLayout");
|
||||
}
|
||||
|
||||
itemSpec.index = -1;
|
||||
this._cols.splice(index, 1);
|
||||
this.onColumnRemoved(itemSpec, index);
|
||||
}
|
||||
|
||||
protected onRowChanged(element: view.View, oldValue: number, newValue: number) {
|
||||
//
|
||||
}
|
||||
|
||||
protected onRowSpanChanged(element: view.View, oldValue: number, newValue: number) {
|
||||
//
|
||||
}
|
||||
|
||||
protected onColumnChanged(element: view.View, oldValue: number, newValue: number) {
|
||||
//
|
||||
}
|
||||
|
||||
protected onColumnSpanChanged(element: view.View, oldValue: number, newValue: number) {
|
||||
//
|
||||
}
|
||||
|
||||
protected onRowAdded(itemSpec: ItemSpec) {
|
||||
//
|
||||
}
|
||||
|
||||
protected onColumnAdded(itemSpec: ItemSpec) {
|
||||
//
|
||||
}
|
||||
|
||||
protected onRowRemoved(itemSpec: ItemSpec, index: number) {
|
||||
//
|
||||
}
|
||||
|
||||
protected onColumnRemoved(itemSpec: ItemSpec, index: number) {
|
||||
//
|
||||
}
|
||||
|
||||
public getColumns(): Array<ItemSpec> {
|
||||
return this._cols.slice();
|
||||
}
|
||||
|
||||
public getRows(): Array<ItemSpec> {
|
||||
return this._rows.slice();
|
||||
}
|
||||
|
||||
protected getColumn(view: view.View): ItemSpec {
|
||||
if (this._cols.length === 0) {
|
||||
return this._singleColumn;
|
||||
}
|
||||
|
||||
var columnIndex = Math.min(GridLayout.getColumn(view), this._cols.length - 1);
|
||||
return this._cols[columnIndex];
|
||||
}
|
||||
|
||||
protected getRow(view: view.View): ItemSpec {
|
||||
if (this._rows.length === 0) {
|
||||
return this._singleRow;
|
||||
}
|
||||
|
||||
var columnIndex = Math.min(GridLayout.getRow(view), this._rows.length - 1);
|
||||
return this._rows[columnIndex];
|
||||
}
|
||||
|
||||
protected getColumnSpan(view: view.View, columnIndex: number): number {
|
||||
if (this._cols.length === 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Math.min(GridLayout.getColumnSpan(view), this._cols.length - columnIndex);
|
||||
}
|
||||
|
||||
protected getRowSpan(view: view.View, rowIndex: number): number {
|
||||
if (this._rows.length === 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Math.min(GridLayout.getRowSpan(view), this._rows.length - rowIndex);
|
||||
}
|
||||
|
||||
protected invalidate(): void {
|
||||
//
|
||||
}
|
||||
|
||||
applyXmlAttribute(attributeName: string, attributeValue: any): boolean {
|
||||
if (attributeName === "columns") {
|
||||
this.setColumns(attributeValue);
|
||||
return true;
|
||||
}
|
||||
else if (attributeName === "rows") {
|
||||
this.setRows(attributeValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static parseItemSpecs(value: string): Array<ItemSpec> {
|
||||
var result = new Array<ItemSpec>();
|
||||
var arr = value.split(",");
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
result.push(GridLayout.convertGridLength(arr[i].trim()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static convertGridLength(value: string): ItemSpec {
|
||||
|
||||
if (value === "auto") {
|
||||
return <ItemSpec>new definition.ItemSpec(1, definition.GridUnitType.auto);
|
||||
}
|
||||
else if (value.indexOf("*") !== -1) {
|
||||
var starCount = parseInt(value.replace("*", "") || "1");
|
||||
return <ItemSpec>new definition.ItemSpec(starCount, definition.GridUnitType.star);
|
||||
}
|
||||
else if (!isNaN(parseInt(value))) {
|
||||
return <ItemSpec>new definition.ItemSpec(parseInt(value), definition.GridUnitType.pixel);
|
||||
}
|
||||
else {
|
||||
throw new Error("Cannot parse item spec from string: " + value);
|
||||
}
|
||||
}
|
||||
|
||||
private static onRowPropertyChanged(data: dependencyObservable.PropertyChangeData): void {
|
||||
var element = GridLayout.getView(data.object);
|
||||
var grid = element.parent;
|
||||
if (grid instanceof GridLayout) {
|
||||
grid.onRowChanged(element, data.oldValue, data.newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static onColumnPropertyChanged(data: dependencyObservable.PropertyChangeData): void {
|
||||
var element = GridLayout.getView(data.object);
|
||||
var grid = element.parent;
|
||||
if (grid instanceof GridLayout) {
|
||||
grid.onColumnChanged(element, data.oldValue, data.newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static onRowSpanPropertyChanged(data: dependencyObservable.PropertyChangeData): void {
|
||||
var element = GridLayout.getView(data.object);
|
||||
var grid = element.parent;
|
||||
if (grid instanceof GridLayout) {
|
||||
grid.onRowSpanChanged(element, data.oldValue, data.newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static onColumnSpanPropertyChanged(data: dependencyObservable.PropertyChangeData): void {
|
||||
var element = GridLayout.getView(data.object);
|
||||
var grid = element.parent;
|
||||
if (grid instanceof GridLayout) {
|
||||
grid.onColumnSpanChanged(element, data.oldValue, data.newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static validateItemSpec(itemSpec: ItemSpec): void {
|
||||
if (!itemSpec) {
|
||||
throw new Error("Value cannot be undefined.");
|
||||
}
|
||||
|
||||
if (itemSpec.owner) {
|
||||
throw new Error("itemSpec is already added to GridLayout.");
|
||||
}
|
||||
}
|
||||
|
||||
private static getView(object: Object): view.View {
|
||||
if (object instanceof view.View) {
|
||||
return object;
|
||||
}
|
||||
|
||||
throw new Error("Element is not View or its descendant.");
|
||||
}
|
||||
|
||||
private setColumns(value: string) {
|
||||
this._cols = GridLayout.parseItemSpecs(value);
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
private setRows(value: string) {
|
||||
this._rows = GridLayout.parseItemSpecs(value);
|
||||
this.invalidate();
|
||||
}
|
||||
}
|
||||
111
ui/layouts/grid-layout/grid-layout.android.ts
Normal file
111
ui/layouts/grid-layout/grid-layout.android.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import definition = require("ui/layouts/grid-layout");
|
||||
import utils = require("utils/utils");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import enums = require("ui/enums");
|
||||
import view = require("ui/core/view");
|
||||
import bindable = require("ui/core/bindable");
|
||||
import types = require("utils/types");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import common = require("ui/layouts/grid-layout/grid-layout-common");
|
||||
|
||||
// merge the exports of the common file with the exports of this file
|
||||
declare var exports;
|
||||
require("utils/module-merge").merge(common, exports);
|
||||
|
||||
|
||||
function setNativeProperty(data: dependencyObservable.PropertyChangeData, setter: (lp: org.nativescript.widgets.CommonLayoutParams) => void) {
|
||||
|
||||
var uiView = data.object;
|
||||
if (uiView instanceof view.View) {
|
||||
var nativeView: android.view.View = uiView._nativeView;
|
||||
|
||||
var lp = <org.nativescript.widgets.CommonLayoutParams>nativeView.getLayoutParams();
|
||||
if (!(lp instanceof org.nativescript.widgets.CommonLayoutParams)) {
|
||||
lp = new org.nativescript.widgets.CommonLayoutParams();
|
||||
}
|
||||
setter(lp);
|
||||
nativeView.setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
|
||||
function setNativeRowProperty(data: dependencyObservable.PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.row = data.newValue; });
|
||||
}
|
||||
|
||||
function setNativeRowSpanProperty(data: dependencyObservable.PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.rowSpan = data.newValue; });
|
||||
}
|
||||
|
||||
function setNativeColumnProperty(data: dependencyObservable.PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.column = data.newValue; });
|
||||
}
|
||||
|
||||
function setNativeColumnSpanProperty(data: dependencyObservable.PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.columnSpan = data.newValue; });
|
||||
}
|
||||
|
||||
(<proxy.PropertyMetadata>common.GridLayout.rowProperty.metadata).onSetNativeValue = setNativeRowProperty;
|
||||
(<proxy.PropertyMetadata>common.GridLayout.rowSpanProperty.metadata).onSetNativeValue = setNativeRowSpanProperty;
|
||||
(<proxy.PropertyMetadata>common.GridLayout.columnProperty.metadata).onSetNativeValue = setNativeColumnProperty;
|
||||
(<proxy.PropertyMetadata>common.GridLayout.columnSpanProperty.metadata).onSetNativeValue = setNativeColumnSpanProperty;
|
||||
|
||||
function createNativeSpec(itemSpec: common.ItemSpec): org.nativescript.widgets.ItemSpec {
|
||||
switch (itemSpec.gridUnitType) {
|
||||
case common.GridUnitType.auto:
|
||||
return new org.nativescript.widgets.ItemSpec(itemSpec.value, org.nativescript.widgets.GridUnitType.auto);
|
||||
|
||||
case common.GridUnitType.star:
|
||||
return new org.nativescript.widgets.ItemSpec(itemSpec.value, org.nativescript.widgets.GridUnitType.star);
|
||||
|
||||
case common.GridUnitType.pixel:
|
||||
return new org.nativescript.widgets.ItemSpec(itemSpec.value * utils.layout.getDisplayDensity(), org.nativescript.widgets.GridUnitType.pixel);
|
||||
|
||||
default:
|
||||
throw new Error("Invalid gridUnitType: " + itemSpec.gridUnitType);
|
||||
}
|
||||
}
|
||||
|
||||
export class GridLayout extends common.GridLayout {
|
||||
|
||||
private _layout: org.nativescript.widgets.GridLayout;
|
||||
|
||||
get android(): org.nativescript.widgets.GridLayout {
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
get _nativeView(): org.nativescript.widgets.GridLayout {
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
public _createUI() {
|
||||
this._layout = new org.nativescript.widgets.GridLayout(this._context);
|
||||
|
||||
// Update native GridLayout
|
||||
this.getRows().forEach((itemSpec, index, rows) => { this.onRowAdded(itemSpec); }, this);
|
||||
this.getColumns().forEach((itemSpec, index, rows) => { this.onColumnAdded(itemSpec); }, this);
|
||||
}
|
||||
|
||||
protected onRowAdded(itemSpec: common.ItemSpec) {
|
||||
if (this._layout) {
|
||||
this._layout.addRow(createNativeSpec(itemSpec));
|
||||
}
|
||||
}
|
||||
|
||||
protected onColumnAdded(itemSpec: common.ItemSpec) {
|
||||
if (this._layout) {
|
||||
this._layout.addColumn(createNativeSpec(itemSpec));
|
||||
}
|
||||
}
|
||||
|
||||
protected onRowRemoved(itemSpec: common.ItemSpec, index: number) {
|
||||
if (this._layout) {
|
||||
this._layout.removeRowAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
protected onColumnRemoved(itemSpec: common.ItemSpec, index: number) {
|
||||
if (this._layout) {
|
||||
this._layout.removeColumnAt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
4
ui/layouts/grid-layout/grid-layout.d.ts
vendored
4
ui/layouts/grid-layout/grid-layout.d.ts
vendored
@@ -1,5 +1,5 @@
|
||||
declare module "ui/layouts/grid-layout" {
|
||||
import layout = require("ui/layouts/layout");
|
||||
import layout = require("ui/layouts/layout-base");
|
||||
import view = require("ui/core/view");
|
||||
|
||||
/**
|
||||
@@ -68,7 +68,7 @@
|
||||
/**
|
||||
* Defines a rectangular layout area that consists of columns and rows.
|
||||
*/
|
||||
export class GridLayout extends layout.Layout {
|
||||
export class GridLayout extends layout.LayoutBase {
|
||||
|
||||
///**
|
||||
// * Initializes a new instance of GridLayout.
|
||||
|
||||
@@ -1,295 +1,54 @@
|
||||
import layouts = require("ui/layouts/layout");
|
||||
import definition = require("ui/layouts/grid-layout");
|
||||
import utils = require("utils/utils");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import utils = require("utils/utils");
|
||||
import enums = require("ui/enums");
|
||||
import view = require("ui/core/view");
|
||||
import bindable = require("ui/core/bindable");
|
||||
import types = require("utils/types");
|
||||
import numberUtils = require("utils/number-utils");
|
||||
import common = require("ui/layouts/grid-layout/grid-layout-common");
|
||||
|
||||
export module GridUnitType {
|
||||
export var auto: string = "auto";
|
||||
export var pixel: string = "pixel";
|
||||
export var star: string = "star";
|
||||
}
|
||||
// merge the exports of the common file with the exports of this file
|
||||
declare var exports;
|
||||
require("utils/module-merge").merge(common, exports);
|
||||
|
||||
export class ItemSpec extends bindable.Bindable implements definition.ItemSpec {
|
||||
|
||||
private _value: number;
|
||||
private _unitType: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
if (arguments.length === 0) {
|
||||
this._value = 1;
|
||||
this._unitType = GridUnitType.star;
|
||||
|
||||
}
|
||||
else if (arguments.length === 2) {
|
||||
if (types.isNumber(arguments[0]) && types.isString(arguments[1])) {
|
||||
if (arguments[0] < 0 || (arguments[1] !== GridUnitType.auto && arguments[1] !== GridUnitType.star && arguments[1] !== GridUnitType.pixel)) {
|
||||
throw new Error("Invalid values.");
|
||||
}
|
||||
this._value = arguments[0];
|
||||
this._unitType = arguments[1];
|
||||
}
|
||||
else {
|
||||
throw new Error("Arguments must be number and string.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error("ItemSpec expects 0 or 2 arguments");
|
||||
}
|
||||
|
||||
this.index = -1;
|
||||
}
|
||||
|
||||
public owner: GridLayout;
|
||||
public index: number;
|
||||
public _actualLength: number = 0;
|
||||
|
||||
public get actualLength(): number {
|
||||
return this._actualLength;
|
||||
}
|
||||
public set actualLength(value: number) {
|
||||
throw new Error("actualLength is read-only property");
|
||||
}
|
||||
|
||||
public static equals(value1: ItemSpec, value2: ItemSpec): boolean {
|
||||
return (value1.gridUnitType === value2.gridUnitType) && (value1.value === value2.value) && (value1.owner === value2.owner) && (value1.index === value2.index);
|
||||
}
|
||||
|
||||
get gridUnitType(): string {
|
||||
return this._unitType;
|
||||
}
|
||||
|
||||
get isAbsolute(): boolean {
|
||||
return this._unitType === GridUnitType.pixel;
|
||||
}
|
||||
|
||||
get isAuto(): boolean {
|
||||
return this._unitType === GridUnitType.auto;
|
||||
}
|
||||
|
||||
get isStar(): boolean {
|
||||
return this._unitType === GridUnitType.star;
|
||||
}
|
||||
|
||||
get value(): number {
|
||||
return this._value;
|
||||
}
|
||||
}
|
||||
|
||||
export class GridLayout extends layouts.Layout implements definition.GridLayout, view.ApplyXmlAttributes {
|
||||
private _rows: Array<ItemSpec> = new Array<ItemSpec>();
|
||||
private _cols: Array<ItemSpec> = new Array<ItemSpec>();
|
||||
private _singleRow: ItemSpec = new ItemSpec();
|
||||
private _singleColumn: ItemSpec = new ItemSpec();
|
||||
export class GridLayout extends common.GridLayout {
|
||||
|
||||
private _isValid: boolean = false;
|
||||
|
||||
private helper: MeasureHelper;
|
||||
|
||||
public static columnProperty = new dependencyObservable.Property("Column", "GridLayout",
|
||||
new dependencyObservable.PropertyMetadata(0, dependencyObservable.PropertyMetadataSettings.None, GridLayout.attachedPropertyChanged, numberUtils.notNegative));
|
||||
public static columnSpanProperty = new dependencyObservable.Property("ColumnSpan", "GridLayout",
|
||||
new dependencyObservable.PropertyMetadata(1, dependencyObservable.PropertyMetadataSettings.None, GridLayout.attachedPropertyChanged, numberUtils.greaterThanZero));
|
||||
|
||||
public static rowProperty = new dependencyObservable.Property("Row", "GridLayout",
|
||||
new dependencyObservable.PropertyMetadata(0, dependencyObservable.PropertyMetadataSettings.None, GridLayout.attachedPropertyChanged, numberUtils.notNegative));
|
||||
public static rowSpanProperty = new dependencyObservable.Property("RowSpan", "GridLayout",
|
||||
new dependencyObservable.PropertyMetadata(1, dependencyObservable.PropertyMetadataSettings.None, GridLayout.attachedPropertyChanged, numberUtils.greaterThanZero));
|
||||
|
||||
public static getColumn(element: view.View): number {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
protected onRowAdded(itemSpec: common.ItemSpec) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
return element._getValue(GridLayout.columnProperty);
|
||||
}
|
||||
|
||||
public static setColumn(element: view.View, value: number): void {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
element._setValue(GridLayout.columnProperty, value);
|
||||
}
|
||||
|
||||
public static getColumnSpan(element: view.View): number {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
return element._getValue(GridLayout.columnSpanProperty);
|
||||
}
|
||||
|
||||
public static setColumnSpan(element: view.View, value: number): void {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
element._setValue(GridLayout.columnSpanProperty, value);
|
||||
}
|
||||
|
||||
public static getRow(element: view.View): number {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
return <number>element._getValue(GridLayout.rowProperty);
|
||||
}
|
||||
|
||||
public static setRow(element: view.View, value: number): void {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
element._setValue(GridLayout.rowProperty, value);
|
||||
}
|
||||
|
||||
public static getRowSpan(element: view.View): number {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
return element._getValue(GridLayout.rowSpanProperty);
|
||||
}
|
||||
|
||||
public static setRowSpan(element: view.View, value: number): void {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
}
|
||||
element._setValue(GridLayout.rowSpanProperty, value);
|
||||
}
|
||||
|
||||
private static attachedPropertyChanged(data: dependencyObservable.PropertyChangeData): void {
|
||||
if (data.object instanceof view.View) {
|
||||
var element = <view.View>data.object;
|
||||
if (!element) {
|
||||
throw new Error("Element is not View.");
|
||||
}
|
||||
|
||||
var grid = element.parent;
|
||||
if (grid instanceof GridLayout) {
|
||||
grid.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static validateItemSpec(itemSpec: ItemSpec): void {
|
||||
if (!itemSpec) {
|
||||
throw new Error("Value cannot be undefined.");
|
||||
}
|
||||
|
||||
if (itemSpec.owner) {
|
||||
throw new Error("itemSpec is already added to GridLayout.");
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._singleRow.index = 0
|
||||
this._singleColumn.index = 0;
|
||||
}
|
||||
|
||||
public addRow(itemSpec: ItemSpec) {
|
||||
GridLayout.validateItemSpec(itemSpec);
|
||||
itemSpec.owner = this;
|
||||
this._rows.push(itemSpec);
|
||||
protected onColumnAdded(itemSpec: common.ItemSpec) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
public addColumn(itemSpec: ItemSpec) {
|
||||
GridLayout.validateItemSpec(itemSpec);
|
||||
itemSpec.owner = this;
|
||||
this._cols.push(itemSpec);
|
||||
protected onRowRemoved(itemSpec: common.ItemSpec, index: number) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
public removeColumn(itemSpec: ItemSpec): void {
|
||||
if (!itemSpec) {
|
||||
throw new Error("Value is null.");
|
||||
}
|
||||
|
||||
var index = this._cols.indexOf(itemSpec);
|
||||
if (itemSpec.owner !== this || index < 0) {
|
||||
throw new Error("Column is not child of this GridLayout");
|
||||
}
|
||||
|
||||
itemSpec.index = -1;
|
||||
this._cols.splice(index, 1);
|
||||
protected onColumnRemoved(itemSpec: common.ItemSpec, index: number) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
public removeRow(itemSpec: ItemSpec): void {
|
||||
if (!itemSpec) {
|
||||
throw new Error("Value is null.");
|
||||
}
|
||||
|
||||
var index = this._rows.indexOf(itemSpec);
|
||||
if (itemSpec.owner !== this || index < 0) {
|
||||
throw new Error("Row is not child of this GridLayout");
|
||||
}
|
||||
|
||||
itemSpec.index = -1;
|
||||
this._rows.splice(index, 1);
|
||||
protected onRowChanged(element: view.View, oldValue: number, newValue: number) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
public getColumns(): Array<ItemSpec> {
|
||||
return this._cols.slice();
|
||||
}
|
||||
|
||||
public getRows(): Array<ItemSpec> {
|
||||
return this._rows.slice();
|
||||
}
|
||||
|
||||
private setColumns(value: string) {
|
||||
this._cols = GridLayout.parseItemSpecs(value);
|
||||
protected onRowSpanChanged(element: view.View, oldValue: number, newValue: number) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
private setRows(value: string) {
|
||||
this._rows = GridLayout.parseItemSpecs(value);
|
||||
protected onColumnChanged(element: view.View, oldValue: number, newValue: number) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
public invalidate(): void {
|
||||
protected onColumnSpanChanged(element: view.View, oldValue: number, newValue: number) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
protected invalidate(): void {
|
||||
this._isValid = false;
|
||||
this.requestLayout();
|
||||
}
|
||||
|
||||
private getColumn(view: view.View): ItemSpec {
|
||||
if (this._cols.length === 0) {
|
||||
return this._singleColumn;
|
||||
}
|
||||
|
||||
var columnIndex = Math.min(GridLayout.getColumn(view), this._cols.length - 1);
|
||||
return this._cols[columnIndex];
|
||||
}
|
||||
|
||||
private getRow(view: view.View): ItemSpec {
|
||||
if (this._rows.length === 0) {
|
||||
return this._singleRow;
|
||||
}
|
||||
|
||||
var columnIndex = Math.min(GridLayout.getRow(view), this._rows.length - 1);
|
||||
return this._rows[columnIndex];
|
||||
}
|
||||
|
||||
private getColumnSpan(view: view.View, columnIndex: number): number {
|
||||
if (this._cols.length === 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Math.min(GridLayout.getColumnSpan(view), this._cols.length - columnIndex);
|
||||
}
|
||||
|
||||
private getRowSpan(view: view.View, rowIndex: number): number {
|
||||
if (this._rows.length === 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Math.min(GridLayout.getRowSpan(view), this._rows.length - rowIndex);
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
@@ -306,17 +65,20 @@ export class GridLayout extends layouts.Layout implements definition.GridLayout,
|
||||
var infinityWidth = widthMode === utils.layout.UNSPECIFIED;
|
||||
var infinityHeight = heightMode === utils.layout.UNSPECIFIED;
|
||||
|
||||
var column: ItemSpec;
|
||||
var column: common.ItemSpec;
|
||||
var columnGroup: ColumnGroup;
|
||||
var row: ItemSpec;
|
||||
var row: common.ItemSpec;
|
||||
var rowGroup: RowGroup;
|
||||
|
||||
var rows = this.getRows();
|
||||
var cols = this.getColumns();
|
||||
if (!this._isValid) {
|
||||
|
||||
this._rows.forEach((value: ItemSpec, index: number, array: ItemSpec[]) => {
|
||||
rows.forEach((value: common.ItemSpec, index: number, array: common.ItemSpec[]) => {
|
||||
value.index = index;
|
||||
});
|
||||
|
||||
this._cols.forEach((value: ItemSpec, index: number, array: ItemSpec[]) => {
|
||||
cols.forEach((value: common.ItemSpec, index: number, array: common.ItemSpec[]) => {
|
||||
value.index = index;
|
||||
});
|
||||
|
||||
@@ -327,8 +89,8 @@ export class GridLayout extends layouts.Layout implements definition.GridLayout,
|
||||
this.helper.infinityWidth = infinityWidth;
|
||||
this.helper.infinityHeight = infinityHeight;
|
||||
|
||||
for (i = 0; i < this._cols.length; i++) {
|
||||
column = this._cols[i];
|
||||
for (i = 0; i < cols.length; i++) {
|
||||
column = cols[i];
|
||||
columnGroup = new ColumnGroup(column, this.helper);
|
||||
this.helper.columns.push(columnGroup);
|
||||
if (column.isAbsolute) {
|
||||
@@ -336,8 +98,8 @@ export class GridLayout extends layouts.Layout implements definition.GridLayout,
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < this._rows.length; i++) {
|
||||
row = this._rows[i];
|
||||
for (i = 0; i < rows.length; i++) {
|
||||
row = rows[i];
|
||||
rowGroup = new RowGroup(row, this.helper);
|
||||
this.helper.rows.push(rowGroup);
|
||||
if (row.isAbsolute) {
|
||||
@@ -345,11 +107,11 @@ export class GridLayout extends layouts.Layout implements definition.GridLayout,
|
||||
}
|
||||
}
|
||||
|
||||
if (this._rows.length === 0) {
|
||||
if (rows.length === 0) {
|
||||
this.helper.rows.push(new RowGroup(this._singleRow, this.helper));
|
||||
}
|
||||
|
||||
if (this._cols.length === 0) {
|
||||
if (cols.length === 0) {
|
||||
this.helper.columns.push(new ColumnGroup(this._singleColumn, this.helper));
|
||||
}
|
||||
}
|
||||
@@ -445,44 +207,6 @@ export class GridLayout extends layouts.Layout implements definition.GridLayout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_applyXmlAttribute(attributeName: string, attributeValue: any): boolean {
|
||||
if (attributeName === "columns") {
|
||||
this.setColumns(attributeValue);
|
||||
return true;
|
||||
}
|
||||
else if (attributeName === "rows") {
|
||||
this.setRows(attributeValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super._applyXmlAttribute(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
private static parseItemSpecs(value: string): Array<ItemSpec> {
|
||||
var result = new Array<ItemSpec>();
|
||||
var arr = value.split(",");
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
result.push(GridLayout.convertGridLength(arr[i].trim()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static convertGridLength(value: string): ItemSpec {
|
||||
|
||||
if (value === "auto") {
|
||||
return <ItemSpec>new definition.ItemSpec(1, definition.GridUnitType.auto);
|
||||
} else if (value.indexOf("*") !== -1) {
|
||||
var starCount = parseInt(value.replace("*", "") || "1");
|
||||
return <ItemSpec>new definition.ItemSpec(starCount, definition.GridUnitType.star);
|
||||
} else if (!isNaN(parseInt(value))) {
|
||||
return <ItemSpec>new definition.ItemSpec(parseInt(value), definition.GridUnitType.pixel);
|
||||
}
|
||||
else {
|
||||
throw new Error("Cannot parse item spec from string: " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MeasureSpecs {
|
||||
@@ -503,8 +227,8 @@ class MeasureSpecs {
|
||||
|
||||
constructor(
|
||||
public child: view.View,
|
||||
public column: ItemSpec,
|
||||
public row: ItemSpec,
|
||||
public column: common.ItemSpec,
|
||||
public row: common.ItemSpec,
|
||||
columnSpan?: number,
|
||||
rowSpan?: number) {
|
||||
// cannot have zero colSpan.
|
||||
@@ -546,14 +270,14 @@ class MeasureSpecs {
|
||||
class ColumnGroup {
|
||||
width: number = 0;
|
||||
measuredCount = 0;
|
||||
column: ItemSpec;
|
||||
column: common.ItemSpec;
|
||||
children: Array<MeasureSpecs> = new Array<MeasureSpecs>();
|
||||
owner: MeasureHelper;
|
||||
|
||||
public measureToFix: number = 0;
|
||||
public currentMeasureToFixCount: number = 0;
|
||||
|
||||
constructor(column: ItemSpec, owner: MeasureHelper) {
|
||||
constructor(column: common.ItemSpec, owner: MeasureHelper) {
|
||||
this.owner = owner;
|
||||
this.column = column;
|
||||
}
|
||||
@@ -587,14 +311,14 @@ class ColumnGroup {
|
||||
class RowGroup {
|
||||
height: number = 0;
|
||||
measuredCount = 0;
|
||||
row: ItemSpec;
|
||||
row: common.ItemSpec;
|
||||
children: Array<MeasureSpecs> = new Array<MeasureSpecs>();
|
||||
owner: MeasureHelper;
|
||||
|
||||
public measureToFix: number = 0;
|
||||
public currentMeasureToFixCount: number = 0;
|
||||
|
||||
constructor(row: ItemSpec, owner: MeasureHelper) {
|
||||
constructor(row: common.ItemSpec, owner: MeasureHelper) {
|
||||
this.row = row;
|
||||
this.owner = owner;
|
||||
}
|
||||
60
ui/layouts/layout-base.d.ts
vendored
Normal file
60
ui/layouts/layout-base.d.ts
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
declare module "ui/layouts/layout-base" {
|
||||
import view = require("ui/core/view");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
|
||||
/**
|
||||
* Base class for all views that supports children positioning.
|
||||
*/
|
||||
export class LayoutBase extends view.CustomLayoutView {
|
||||
|
||||
public static clipToBoundsProperty: dependencyObservable.Property;
|
||||
|
||||
/**
|
||||
* Returns the number of children in this Layout.
|
||||
*/
|
||||
getChildrenCount(): number;
|
||||
|
||||
/**
|
||||
* Returns the view at the specified position.
|
||||
* @param index The position at which to get the child from.
|
||||
*/
|
||||
getChildAt(index: number): view.View;
|
||||
|
||||
/**
|
||||
* Adds the view to children array.
|
||||
* @param view The view to be added to the end of the children array.
|
||||
*/
|
||||
addChild(view: view.View);
|
||||
|
||||
/**
|
||||
* Removes the specified view from the children array.
|
||||
* @param view The view to remove from the children array.
|
||||
*/
|
||||
removeChild(view: view.View);
|
||||
|
||||
/**
|
||||
* Gets or sets padding style property.
|
||||
*/
|
||||
padding: string;
|
||||
|
||||
/**
|
||||
* Specify the bottom padding of this layout.
|
||||
*/
|
||||
paddingBottom: number;
|
||||
|
||||
/**
|
||||
* Specify the left padding of this layout.
|
||||
*/
|
||||
paddingLeft: number;
|
||||
|
||||
/**
|
||||
* Specify the right padding of this layout.
|
||||
*/
|
||||
paddingRight: number;
|
||||
|
||||
/**
|
||||
* Specify the top padding of this layout.
|
||||
*/
|
||||
paddingTop: number;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,12 @@
|
||||
import definition = require("ui/layouts/layout");
|
||||
import definition = require("ui/layouts/layout-base");
|
||||
import view = require("ui/core/view");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import proxy = require("ui/core/proxy");
|
||||
|
||||
function onClipToBoundsPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
var nativeView = (<Layout>data.object)._nativeView;
|
||||
if (!nativeView) {
|
||||
return;
|
||||
}
|
||||
var value = <boolean>data.newValue;
|
||||
export class LayoutBase extends view.CustomLayoutView implements definition.LayoutBase, view.AddChildFromBuilder {
|
||||
|
||||
if (nativeView instanceof UIView) {
|
||||
(<UIView>nativeView).clipsToBounds = value;
|
||||
}
|
||||
else if (nativeView instanceof android.view.ViewGroup) {
|
||||
(<android.view.ViewGroup>nativeView).setClipChildren(value);
|
||||
}
|
||||
}
|
||||
|
||||
var clipToBoundsProperty = new dependencyObservable.Property(
|
||||
"clipToBounds",
|
||||
"Layout",
|
||||
new proxy.PropertyMetadata(undefined, dependencyObservable.PropertyMetadataSettings.None, onClipToBoundsPropertyChanged)
|
||||
);
|
||||
|
||||
export class Layout extends view.CustomLayoutView implements definition.Layout, view.AddChildFromBuilder {
|
||||
public static clipToBoundsProperty = clipToBoundsProperty;
|
||||
public static clipToBoundsProperty = new dependencyObservable.Property("clipToBounds", "LayoutBase",
|
||||
new proxy.PropertyMetadata(true, dependencyObservable.PropertyMetadataSettings.None, LayoutBase.onClipToBoundsPropertyChanged));
|
||||
|
||||
private _subViews: Array<view.View> = new Array<view.View>();
|
||||
|
||||
@@ -88,6 +69,13 @@ export class Layout extends view.CustomLayoutView implements definition.Layout,
|
||||
}
|
||||
}
|
||||
|
||||
get padding(): string {
|
||||
return this.style.padding;
|
||||
}
|
||||
set padding(value: string) {
|
||||
this.style.padding = value;
|
||||
}
|
||||
|
||||
public get paddingTop(): number {
|
||||
return this.style.paddingTop;
|
||||
}
|
||||
@@ -116,10 +104,12 @@ export class Layout extends view.CustomLayoutView implements definition.Layout,
|
||||
this.style.paddingLeft = value;
|
||||
}
|
||||
|
||||
get clipToBounds(): boolean {
|
||||
return this._getValue(Layout.clipToBoundsProperty);
|
||||
protected onClipToBoundsChanged(oldValue: boolean, newValue: boolean) {
|
||||
//
|
||||
}
|
||||
|
||||
private static onClipToBoundsPropertyChanged(data: dependencyObservable.PropertyChangeData): void {
|
||||
var layout = <LayoutBase>data.object;
|
||||
layout.onClipToBoundsChanged(data.oldValue, data.newValue);
|
||||
}
|
||||
set clipToBounds(value: boolean) {
|
||||
this._setValue(Layout.clipToBoundsProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
72
ui/layouts/layout.android.ts
Normal file
72
ui/layouts/layout.android.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import definition = require("ui/layouts/layout");
|
||||
import view = require("ui/core/view");
|
||||
import layoutBase = require("ui/layouts/layout-base");
|
||||
import trace = require("trace");
|
||||
import utils = require("utils/utils");
|
||||
import proxy = require("ui/core/proxy");
|
||||
|
||||
var OWNER = "_owner";
|
||||
|
||||
export class Layout extends layoutBase.LayoutBase implements definition.Layout {
|
||||
private _viewGroup: android.view.ViewGroup;
|
||||
|
||||
get android(): android.view.ViewGroup {
|
||||
return this._viewGroup;
|
||||
}
|
||||
|
||||
get _nativeView(): android.view.ViewGroup {
|
||||
return this._viewGroup;
|
||||
}
|
||||
|
||||
public _createUI() {
|
||||
this._viewGroup = new view.NativeViewGroup(this._context);
|
||||
this._viewGroup[OWNER] = this;
|
||||
}
|
||||
|
||||
public _onDetached(force?: boolean) {
|
||||
delete this._viewGroup[OWNER];
|
||||
super._onDetached(force);
|
||||
}
|
||||
|
||||
public measure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
this._setCurrentMeasureSpecs(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
var view = this._nativeView;
|
||||
if (view) {
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
trace.write(this + " :measure: " + utils.layout.getMode(widthMode) + " " + width + ", " + utils.layout.getMode(heightMode) + " " + height, trace.categories.Layout);
|
||||
view.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
|
||||
public layout(left: number, top: number, right: number, bottom: number): void {
|
||||
this._setCurrentLayoutBounds(left, top, right, bottom);
|
||||
|
||||
var view = this._nativeView;
|
||||
if (view) {
|
||||
this.layoutNativeView(left, top, right, bottom);
|
||||
trace.write(this + " :layout: " + left + ", " + top + ", " + (right - left) + ", " + (bottom - top), trace.categories.Layout);
|
||||
}
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
// Don't call super because it will trigger measure again.
|
||||
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
trace.write(this + " :onMeasure: " + utils.layout.getMode(widthMode) + " " + width + ", " + utils.layout.getMode(heightMode) + " " + height, trace.categories.Layout);
|
||||
}
|
||||
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
// Don't call super because it will trigger layout again.
|
||||
trace.write(this + " :onLayout: " + left + ", " + top + ", " + (right - left) + ", " + (bottom - top), trace.categories.Layout);
|
||||
}
|
||||
}
|
||||
64
ui/layouts/layout.d.ts
vendored
64
ui/layouts/layout.d.ts
vendored
@@ -1,65 +1,11 @@
|
||||
declare module "ui/layouts/layout" {
|
||||
import view = require("ui/core/view");
|
||||
import layoutBase = require("ui/layouts/layout-base");
|
||||
|
||||
/**
|
||||
* Base class for all views that supports children positioning.
|
||||
* Base class for all views that supports children positioning in cross platform manner.
|
||||
*/
|
||||
export class Layout extends view.View {
|
||||
|
||||
/**
|
||||
* Returns the number of children in this Layout.
|
||||
*/
|
||||
getChildrenCount(): number;
|
||||
|
||||
/**
|
||||
* Returns the view at the specified position.
|
||||
* @param index The position at which to get the child from.
|
||||
*/
|
||||
getChildAt(index: number): view.View;
|
||||
|
||||
/**
|
||||
* Returns the position of the child view
|
||||
* @param child The child view that we are looking for.
|
||||
*/
|
||||
getChildIndex(child: view.View): number;
|
||||
|
||||
/**
|
||||
* Adds the view to children array.
|
||||
* @param view The view to be added to the end of the children array.
|
||||
*/
|
||||
addChild(view: view.View);
|
||||
|
||||
/**
|
||||
* Inserts the view to children array at the specified index.
|
||||
* @param atIndex The insertion index.
|
||||
* @param view The view to be added to the end of the children array.
|
||||
*/
|
||||
insertChild(atIndex: number, child: view.View);
|
||||
|
||||
/**
|
||||
* Removes the specified view from the children array.
|
||||
* @param view The view to remove from the children array.
|
||||
*/
|
||||
removeChild(view: view.View);
|
||||
|
||||
/**
|
||||
* Specify the bottom padding of this layout.
|
||||
*/
|
||||
paddingBottom: number;
|
||||
|
||||
/**
|
||||
* Specify the left padding of this layout.
|
||||
*/
|
||||
paddingLeft: number;
|
||||
|
||||
/**
|
||||
* Specify the right padding of this layout.
|
||||
*/
|
||||
paddingRight: number;
|
||||
|
||||
/**
|
||||
* Specify the top padding of this layout.
|
||||
*/
|
||||
paddingTop: number;
|
||||
export class Layout extends layoutBase.LayoutBase {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
41
ui/layouts/layout.ios.ts
Normal file
41
ui/layouts/layout.ios.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import definition = require("ui/layouts/layout");
|
||||
import layoutBase = require("ui/layouts/layout-base");
|
||||
import trace = require("trace");
|
||||
import utils = require("utils/utils");
|
||||
|
||||
export class Layout extends layoutBase.LayoutBase implements definition.Layout {
|
||||
|
||||
private _view: UIView;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._view = new UIView();
|
||||
this._view.autoresizesSubviews = false;
|
||||
}
|
||||
|
||||
get ios(): UIView {
|
||||
return this._view;
|
||||
}
|
||||
|
||||
get _nativeView(): UIView {
|
||||
return this._view;
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
// Don't call super because it will measure the native element.
|
||||
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
trace.write(this + " :onMeasure: " + utils.layout.getMode(widthMode) + " " + width + ", " + utils.layout.getMode(heightMode) + " " + height, trace.categories.Layout);
|
||||
}
|
||||
|
||||
protected onClipToBoundsChanged(oldValue: boolean, newValue: boolean): void {
|
||||
if (this._nativeView) {
|
||||
this._nativeView.clipsToBounds = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
ui/layouts/stack-layout/stack-layout-common.ts
Normal file
25
ui/layouts/stack-layout/stack-layout-common.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import layouts = require("ui/layouts/layout-base");
|
||||
import definition = require("ui/layouts/stack-layout");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import enums = require("ui/enums");
|
||||
import proxy = require("ui/core/proxy");
|
||||
|
||||
// on Android we explicitly set propertySettings to None because android will invalidate its layout (skip unnecessary native call).
|
||||
var AffectsLayout = global.android ? dependencyObservable.PropertyMetadataSettings.None : dependencyObservable.PropertyMetadataSettings.AffectsLayout;
|
||||
|
||||
function validateOrientation(value: any): boolean {
|
||||
return value === enums.Orientation.vertical || value === enums.Orientation.horizontal;
|
||||
}
|
||||
|
||||
export class StackLayout extends layouts.LayoutBase implements definition.StackLayout {
|
||||
|
||||
public static orientationProperty = new dependencyObservable.Property("orientation","StackLayout",
|
||||
new proxy.PropertyMetadata(enums.Orientation.vertical, AffectsLayout, undefined, validateOrientation));
|
||||
|
||||
get orientation(): string {
|
||||
return this._getValue(StackLayout.orientationProperty);
|
||||
}
|
||||
set orientation(value: string) {
|
||||
this._setValue(StackLayout.orientationProperty, value);
|
||||
}
|
||||
}
|
||||
38
ui/layouts/stack-layout/stack-layout.android.ts
Normal file
38
ui/layouts/stack-layout/stack-layout.android.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import common = require("ui/layouts/stack-layout/stack-layout-common");
|
||||
import enums = require("ui/enums");
|
||||
|
||||
// merge the exports of the common file with the exports of this file
|
||||
declare var exports;
|
||||
require("utils/module-merge").merge(common, exports);
|
||||
|
||||
export class StackLayout extends common.StackLayout {
|
||||
|
||||
static setNativeOrientationProperty(data: dependencyObservable.PropertyChangeData): void {
|
||||
var stackLayout = <StackLayout>data.object;
|
||||
var nativeView = stackLayout._nativeView;
|
||||
if (data.newValue === enums.Orientation.vertical) {
|
||||
nativeView.setOrientation(org.nativescript.widgets.Orientation.vertical);
|
||||
}
|
||||
else {
|
||||
nativeView.setOrientation(org.nativescript.widgets.Orientation.horzontal);
|
||||
}
|
||||
}
|
||||
|
||||
private _layout: org.nativescript.widgets.StackLayout;
|
||||
|
||||
get android(): org.nativescript.widgets.StackLayout {
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
get _nativeView(): org.nativescript.widgets.StackLayout {
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
public _createUI() {
|
||||
this._layout = new org.nativescript.widgets.StackLayout(this._context);
|
||||
}
|
||||
}
|
||||
|
||||
(<proxy.PropertyMetadata>common.StackLayout.orientationProperty.metadata).onSetNativeValue = StackLayout.setNativeOrientationProperty;
|
||||
4
ui/layouts/stack-layout/stack-layout.d.ts
vendored
4
ui/layouts/stack-layout/stack-layout.d.ts
vendored
@@ -1,11 +1,11 @@
|
||||
declare module "ui/layouts/stack-layout" {
|
||||
import layout = require("ui/layouts/layout");
|
||||
import layout = require("ui/layouts/layout-base");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
|
||||
/**
|
||||
* A Layout that arranges its children horizontally or vertically. The direction can be set by orientation property.
|
||||
*/
|
||||
class StackLayout extends layout.Layout {
|
||||
class StackLayout extends layout.LayoutBase {
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the orientation property of each StackLayout instance.
|
||||
|
||||
@@ -1,35 +1,16 @@
|
||||
import layouts = require("ui/layouts/layout");
|
||||
import definition = require("ui/layouts/stack-layout");
|
||||
import utils = require("utils/utils");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import utils = require("utils/utils");
|
||||
import enums = require("ui/enums");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import view = require("ui/core/view");
|
||||
import common = require("ui/layouts/stack-layout/stack-layout-common");
|
||||
|
||||
function validateOrientation(value: any): boolean {
|
||||
return value === enums.Orientation.vertical || value === enums.Orientation.horizontal;
|
||||
}
|
||||
// merge the exports of the common file with the exports of this file
|
||||
declare var exports;
|
||||
require("utils/module-merge").merge(common, exports);
|
||||
|
||||
export var orientationProperty = new dependencyObservable.Property(
|
||||
"orientation",
|
||||
"StackLayout",
|
||||
new proxy.PropertyMetadata(enums.Orientation.vertical,
|
||||
dependencyObservable.PropertyMetadataSettings.AffectsLayout,
|
||||
undefined,
|
||||
validateOrientation)
|
||||
);
|
||||
|
||||
export class StackLayout extends layouts.Layout implements definition.StackLayout {
|
||||
export class StackLayout extends common.StackLayout {
|
||||
|
||||
private _totalLength = 0;
|
||||
|
||||
get orientation(): string {
|
||||
return this._getValue(orientationProperty);
|
||||
}
|
||||
set orientation(value: string) {
|
||||
this._setValue(orientationProperty, value);
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
var density = utils.layout.getDisplayDensity();
|
||||
49
ui/layouts/wrap-layout/wrap-layout-common.ts
Normal file
49
ui/layouts/wrap-layout/wrap-layout-common.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import layouts = require("ui/layouts/layout-base");
|
||||
import definition = require("ui/layouts/wrap-layout");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import enums = require("ui/enums");
|
||||
import proxy = require("ui/core/proxy");
|
||||
|
||||
// on Android we explicitly set propertySettings to None because android will invalidate its layout (so we skip unnecessary native call).
|
||||
var AffectsLayout = global.android ? dependencyObservable.PropertyMetadataSettings.None : dependencyObservable.PropertyMetadataSettings.AffectsLayout;
|
||||
|
||||
function isWidthHeightValid(value: any): boolean {
|
||||
return (value >= 0.0 && value !== Number.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
function isValidOrientation(value: any): boolean {
|
||||
return value === enums.Orientation.vertical || value === enums.Orientation.horizontal;
|
||||
}
|
||||
|
||||
export class WrapLayout extends layouts.LayoutBase implements definition.WrapLayout {
|
||||
|
||||
public static orientationProperty = new dependencyObservable.Property("orientation", "WrapLayout",
|
||||
new proxy.PropertyMetadata(enums.Orientation.horizontal, AffectsLayout, undefined, isValidOrientation));
|
||||
|
||||
public static itemWidthProperty = new dependencyObservable.Property("itemWidth", "WrapLayout",
|
||||
new proxy.PropertyMetadata(0, AffectsLayout, undefined, isWidthHeightValid));
|
||||
|
||||
public static itemHeightProperty = new dependencyObservable.Property("itemHeight", "WrapLayout",
|
||||
new proxy.PropertyMetadata(0, AffectsLayout, undefined, isWidthHeightValid));
|
||||
|
||||
get orientation(): string {
|
||||
return this._getValue(WrapLayout.orientationProperty);
|
||||
}
|
||||
set orientation(value: string) {
|
||||
this._setValue(WrapLayout.orientationProperty, value);
|
||||
}
|
||||
|
||||
get itemWidth(): number {
|
||||
return this._getValue(WrapLayout.itemWidthProperty);
|
||||
}
|
||||
set itemWidth(value: number) {
|
||||
this._setValue(WrapLayout.itemWidthProperty, value);
|
||||
}
|
||||
|
||||
get itemHeight(): number {
|
||||
return this._getValue(WrapLayout.itemHeightProperty);
|
||||
}
|
||||
set itemHeight(value: number) {
|
||||
this._setValue(WrapLayout.itemHeightProperty, value);
|
||||
}
|
||||
}
|
||||
46
ui/layouts/wrap-layout/wrap-layout.android.ts
Normal file
46
ui/layouts/wrap-layout/wrap-layout.android.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import common = require("ui/layouts/wrap-layout/wrap-layout-common");
|
||||
|
||||
// merge the exports of the common file with the exports of this file
|
||||
declare var exports;
|
||||
require("utils/module-merge").merge(common, exports);
|
||||
|
||||
export class WrapLayout extends common.WrapLayout {
|
||||
|
||||
static setNativeOrientationProperty(data: dependencyObservable.PropertyChangeData): void {
|
||||
var wrapLayout = <WrapLayout>data.object;
|
||||
var nativeView = wrapLayout._nativeView;
|
||||
nativeView.setOrientation(data.newValue);
|
||||
}
|
||||
|
||||
static setNativeItemWidthProperty(data: dependencyObservable.PropertyChangeData): void {
|
||||
var wrapLayout = <WrapLayout>data.object;
|
||||
var nativeView = wrapLayout._nativeView;
|
||||
nativeView.setItemWidth(data.newValue);
|
||||
}
|
||||
|
||||
static setNativeItemHeightProperty(data: dependencyObservable.PropertyChangeData): void {
|
||||
var wrapLayout = <WrapLayout>data.object;
|
||||
var nativeView = wrapLayout._nativeView;
|
||||
nativeView.setItemHeight(data.newValue);
|
||||
}
|
||||
|
||||
private _layout: org.nativescript.widgets.WrapLayout;
|
||||
|
||||
get android(): org.nativescript.widgets.WrapLayout {
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
get _nativeView(): org.nativescript.widgets.WrapLayout {
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
public _createUI() {
|
||||
this._layout = new org.nativescript.widgets.WrapLayout(this._context);
|
||||
}
|
||||
}
|
||||
|
||||
(<proxy.PropertyMetadata>common.WrapLayout.orientationProperty.metadata).onSetNativeValue = WrapLayout.setNativeOrientationProperty;
|
||||
(<proxy.PropertyMetadata>common.WrapLayout.orientationProperty.metadata).onSetNativeValue = WrapLayout.setNativeItemWidthProperty;
|
||||
(<proxy.PropertyMetadata>common.WrapLayout.orientationProperty.metadata).onSetNativeValue = WrapLayout.setNativeItemHeightProperty;
|
||||
4
ui/layouts/wrap-layout/wrap-layout.d.ts
vendored
4
ui/layouts/wrap-layout/wrap-layout.d.ts
vendored
@@ -1,12 +1,12 @@
|
||||
declare module "ui/layouts/wrap-layout" {
|
||||
import layout = require("ui/layouts/layout");
|
||||
import layout = require("ui/layouts/layout-base");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
|
||||
/**
|
||||
* WrapLayout position children in rows or columns depending on orientation property
|
||||
* until space is filled and then wraps them on new row or column.
|
||||
*/
|
||||
class WrapLayout extends layout.Layout {
|
||||
class WrapLayout extends layout.LayoutBase {
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the orientation property of each WrapLayout instance.
|
||||
|
||||
@@ -1,73 +1,20 @@
|
||||
import layouts = require("ui/layouts/layout");
|
||||
import definition = require("ui/layouts/wrap-layout");
|
||||
import utils = require("utils/utils");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import utils = require("utils/utils");
|
||||
import view = require("ui/core/view");
|
||||
import enums = require("ui/enums");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import common = require("ui/layouts/wrap-layout/wrap-layout-common");
|
||||
|
||||
function isWidthHeightValid(value: any): boolean {
|
||||
return isNaN(value) || (value >= 0.0 && value !== Number.POSITIVE_INFINITY);
|
||||
}
|
||||
// merge the exports of the common file with the exports of this file
|
||||
declare var exports;
|
||||
require("utils/module-merge").merge(common, exports);
|
||||
|
||||
function isValidOrientation(value: any): boolean {
|
||||
return value === enums.Orientation.vertical || value === enums.Orientation.horizontal;
|
||||
}
|
||||
|
||||
export class WrapLayout extends layouts.Layout implements definition.WrapLayout {
|
||||
export class WrapLayout extends common.WrapLayout {
|
||||
|
||||
private _lenghts: Array<number>;
|
||||
|
||||
public static orientationProperty = new dependencyObservable.Property(
|
||||
"orientation",
|
||||
"WrapLayout",
|
||||
new proxy.PropertyMetadata(enums.Orientation.horizontal,
|
||||
dependencyObservable.PropertyMetadataSettings.AffectsLayout,
|
||||
undefined,
|
||||
isValidOrientation)
|
||||
);
|
||||
|
||||
public static itemWidthProperty = new dependencyObservable.Property(
|
||||
"itemWidth",
|
||||
"WrapLayout",
|
||||
new proxy.PropertyMetadata(Number.NaN,
|
||||
dependencyObservable.PropertyMetadataSettings.AffectsLayout,
|
||||
undefined,
|
||||
isWidthHeightValid)
|
||||
);
|
||||
|
||||
public static itemHeightProperty = new dependencyObservable.Property(
|
||||
"itemHeight",
|
||||
"WrapLayout",
|
||||
new proxy.PropertyMetadata(Number.NaN,
|
||||
dependencyObservable.PropertyMetadataSettings.AffectsLayout,
|
||||
undefined,
|
||||
isWidthHeightValid)
|
||||
);
|
||||
|
||||
get orientation(): string {
|
||||
return this._getValue(WrapLayout.orientationProperty);
|
||||
}
|
||||
set orientation(value: string) {
|
||||
this._setValue(WrapLayout.orientationProperty, value);
|
||||
}
|
||||
|
||||
get itemWidth(): number {
|
||||
return this._getValue(WrapLayout.itemWidthProperty);
|
||||
}
|
||||
set itemWidth(value: number) {
|
||||
this._setValue(WrapLayout.itemWidthProperty, value);
|
||||
}
|
||||
|
||||
get itemHeight(): number {
|
||||
return this._getValue(WrapLayout.itemHeightProperty);
|
||||
}
|
||||
set itemHeight(value: number) {
|
||||
this._setValue(WrapLayout.itemHeightProperty, value);
|
||||
}
|
||||
|
||||
private static getChildMeasureSpec(parentMode: number, parentLength: number, itemLength): number {
|
||||
if (!isNaN(itemLength)) {
|
||||
if (itemLength > 0) {
|
||||
return utils.layout.makeMeasureSpec(itemLength, utils.layout.EXACTLY);
|
||||
}
|
||||
else if (parentMode === utils.layout.UNSPECIFIED) {
|
||||
@@ -1,5 +1,4 @@
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import view = require("ui/core/view");
|
||||
import definition = require("ui/scroll-view");
|
||||
import contentView = require("ui/content-view");
|
||||
import common = require("ui/scroll-view/scroll-view-common");
|
||||
@@ -8,97 +7,12 @@ import enums = require("ui/enums");
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
|
||||
var OWNER = "_owner";
|
||||
var STATE = "_scrollViewState";
|
||||
|
||||
common.orientationProperty.metadata.onValueChanged = function scrollViewOrientationChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
(<ScrollView>data.object)._onOrientationChanged(data.oldValue, data.newValue);
|
||||
}
|
||||
|
||||
interface ScrollViewState {
|
||||
scrollX: number;
|
||||
scrollY: number;
|
||||
}
|
||||
|
||||
function onMeasureScrollView(widthMeasureSpec: number, heightMeasureSpec: number) {
|
||||
var owner: view.View = this.owner;
|
||||
owner.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
this.setMeasuredDimension(owner.getMeasuredWidth(), owner.getMeasuredHeight());
|
||||
}
|
||||
|
||||
function onLayoutScrollView(changed: boolean, left: number, top: number, right: number, bottom: number) {
|
||||
var owner: view.View = this.owner;
|
||||
owner.onLayout(left, top, right, bottom);
|
||||
|
||||
// Restore scroll state on the first layout after native instance is recreated.
|
||||
var state: ScrollViewState = owner[STATE];
|
||||
if (state) {
|
||||
this.scrollTo(state.scrollX, state.scrollY);
|
||||
delete owner[STATE];
|
||||
}
|
||||
}
|
||||
|
||||
function onSaveInstanceStateNative(): android.os.Parcelable {
|
||||
var state: ScrollViewState = {
|
||||
scrollX: this.getScrollX(),
|
||||
scrollY: this.getScrollY()
|
||||
}
|
||||
this.owner[STATE] = state;
|
||||
return this.super.onSaveInstanceState();
|
||||
}
|
||||
|
||||
class NativeVerticalScrollView extends android.widget.ScrollView {
|
||||
constructor(ctx) {
|
||||
super(ctx);
|
||||
return global.__native(this);
|
||||
}
|
||||
|
||||
get owner() {
|
||||
return this[OWNER];
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number) {
|
||||
onMeasureScrollView.apply(this, [widthMeasureSpec, heightMeasureSpec]);
|
||||
}
|
||||
|
||||
public onLayout(changed: boolean, left: number, top: number, right: number, bottom: number) {
|
||||
onLayoutScrollView.apply(this, [changed, left, top, right, bottom]);
|
||||
}
|
||||
|
||||
public onSaveInstanceState() {
|
||||
onSaveInstanceStateNative.apply(this, []);
|
||||
}
|
||||
};
|
||||
|
||||
class NativeHorizontalScrollView extends android.widget.HorizontalScrollView {
|
||||
constructor(ctx) {
|
||||
super(ctx);
|
||||
return global.__native(this);
|
||||
}
|
||||
|
||||
get owner() {
|
||||
return this[OWNER];
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number) {
|
||||
onMeasureScrollView.apply(this, [widthMeasureSpec, heightMeasureSpec]);
|
||||
}
|
||||
|
||||
public onLayout(changed: boolean, left: number, top: number, right: number, bottom: number) {
|
||||
onLayoutScrollView.apply(this, [changed, left, top, right, bottom]);
|
||||
}
|
||||
|
||||
public onSaveInstanceState() {
|
||||
onSaveInstanceStateNative.apply(this, []);
|
||||
}
|
||||
};
|
||||
|
||||
export class ScrollView extends contentView.ContentView implements definition.ScrollView {
|
||||
private _android: android.widget.FrameLayout;
|
||||
private _contentMeasuredWidth: number = 0;
|
||||
private _contentMeasuredHeight: number = 0;
|
||||
|
||||
private _scrollableLength: number = 0;
|
||||
private _android: org.nativescript.widgets.VerticalScrollView | org.nativescript.widgets.HorizontalScrollView;
|
||||
private _androidViewId: number;
|
||||
|
||||
get android(): android.view.ViewGroup {
|
||||
@@ -137,7 +51,7 @@ export class ScrollView extends contentView.ContentView implements definition.Sc
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._scrollableLength;
|
||||
return this._android.getScrollableLength();
|
||||
}
|
||||
|
||||
get scrollableHeight(): number {
|
||||
@@ -145,19 +59,18 @@ export class ScrollView extends contentView.ContentView implements definition.Sc
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._scrollableLength;
|
||||
return this._android.getScrollableLength();
|
||||
}
|
||||
|
||||
public scrollToVerticalOffset(value: number, animated: boolean) {
|
||||
if (this._android && this.orientation === enums.Orientation.vertical) {
|
||||
value *= utils.layout.getDisplayDensity();
|
||||
|
||||
var scrollView: android.widget.ScrollView = (<android.widget.ScrollView>this._android);
|
||||
if (animated) {
|
||||
scrollView.smoothScrollTo(0, value);
|
||||
this._android.smoothScrollTo(0, value);
|
||||
}
|
||||
else {
|
||||
scrollView.scrollTo(0, value);
|
||||
this._android.scrollTo(0, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,30 +79,28 @@ export class ScrollView extends contentView.ContentView implements definition.Sc
|
||||
if (this._android && this.orientation === enums.Orientation.horizontal) {
|
||||
value *= utils.layout.getDisplayDensity();
|
||||
|
||||
var scrollView: android.widget.HorizontalScrollView = (<android.widget.HorizontalScrollView>this._android);
|
||||
if (animated) {
|
||||
scrollView.smoothScrollTo(value, 0);
|
||||
this._android.smoothScrollTo(value, 0);
|
||||
}
|
||||
else {
|
||||
scrollView.scrollTo(value, 0);
|
||||
this._android.scrollTo(value, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public _createUI() {
|
||||
if (this.orientation === enums.Orientation.horizontal) {
|
||||
this._android = new NativeHorizontalScrollView(this._context);
|
||||
this._android = new org.nativescript.widgets.HorizontalScrollView(this._context);
|
||||
}
|
||||
else {
|
||||
this._android = new NativeVerticalScrollView(this._context);
|
||||
this._android = new org.nativescript.widgets.VerticalScrollView(this._context);
|
||||
}
|
||||
|
||||
if (!this._androidViewId) {
|
||||
this._androidViewId = android.view.View.generateViewId();
|
||||
}
|
||||
this._android.setId(this._androidViewId);
|
||||
|
||||
this._android[OWNER] = this;
|
||||
this._android.setId(this._androidViewId);
|
||||
}
|
||||
|
||||
public _onOrientationChanged(oldValue: string, newValue: string) {
|
||||
@@ -205,56 +116,4 @@ export class ScrollView extends contentView.ContentView implements definition.Sc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
// Don't call measure because it will measure content twice.
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
var density = utils.layout.getDisplayDensity();
|
||||
var child = this.content
|
||||
if (!child) {
|
||||
this._scrollableLength = 0;
|
||||
this._contentMeasuredWidth = this.minWidth * density;
|
||||
this._contentMeasuredHeight = this.minHeight * density;
|
||||
}
|
||||
else {
|
||||
var childSize: { measuredWidth: number; measuredHeight: number };
|
||||
if (this.orientation === enums.Orientation.vertical) {
|
||||
childSize = view.View.measureChild(this, child, widthMeasureSpec, utils.layout.makeMeasureSpec(0, utils.layout.UNSPECIFIED));
|
||||
}
|
||||
else {
|
||||
childSize = view.View.measureChild(this, child, utils.layout.makeMeasureSpec(0, utils.layout.UNSPECIFIED), heightMeasureSpec);
|
||||
}
|
||||
|
||||
this._contentMeasuredWidth = Math.max(childSize.measuredWidth, this.minWidth * density);
|
||||
this._contentMeasuredHeight = Math.max(childSize.measuredHeight, this.minHeight * density);
|
||||
}
|
||||
|
||||
var widthAndState = view.View.resolveSizeAndState(this._contentMeasuredWidth, width, widthMode, 0);
|
||||
var heightAndState = view.View.resolveSizeAndState(this._contentMeasuredHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
|
||||
var width = (right - left);
|
||||
var height = (bottom - top);
|
||||
|
||||
if (this.orientation === enums.Orientation.horizontal) {
|
||||
this._scrollableLength = this._contentMeasuredWidth - width;
|
||||
view.View.layoutChild(this, this.content, 0, 0, Math.max(this._contentMeasuredWidth, width), height);
|
||||
}
|
||||
else {
|
||||
this._scrollableLength = this._contentMeasuredHeight - height;
|
||||
view.View.layoutChild(this, this.content, 0, 0, width, Math.max(this._contentMeasuredHeight, height));
|
||||
}
|
||||
|
||||
this._scrollableLength /= utils.layout.getDisplayDensity();
|
||||
this._scrollableLength = Math.max(0, this._scrollableLength);
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,216 @@ var _handlersCache = {};
|
||||
// classes like Frame that does not need to handle styling properties.
|
||||
var noStylingClasses = {};
|
||||
|
||||
// on Android we explicitly set propertySettings to None because android will invalidate its layout (skip unnecessary native call).
|
||||
var AffectsLayout = global.android ? dependencyObservable.PropertyMetadataSettings.None : dependencyObservable.PropertyMetadataSettings.AffectsLayout;
|
||||
|
||||
export interface Thickness {
|
||||
left: number;
|
||||
top: number;
|
||||
right: number;
|
||||
bottom: number;
|
||||
}
|
||||
|
||||
export interface CommonLayoutParams {
|
||||
width: number;
|
||||
height: number;
|
||||
|
||||
leftMargin: number;
|
||||
topMargin: number;
|
||||
rightMargin: number;
|
||||
bottomMargin: number;
|
||||
|
||||
horizontalAlignment: string;
|
||||
verticalAlignment: string;
|
||||
}
|
||||
|
||||
function parseThickness(value: any): Thickness {
|
||||
var result: Thickness = { top: 0, right: 0, bottom: 0, left: 0 };
|
||||
if (types.isString(value)) {
|
||||
var arr = value.split(/[ ,]+/);
|
||||
var top = parseInt(arr[0]);
|
||||
top = isNaN(top) ? 0 : top;
|
||||
|
||||
var right = parseInt(arr[1]);
|
||||
right = isNaN(right) ? top : right;
|
||||
|
||||
var bottom = parseInt(arr[2]);
|
||||
bottom = isNaN(bottom) ? top : bottom;
|
||||
|
||||
var left = parseInt(arr[3]);
|
||||
left = isNaN(left) ? right : left;
|
||||
|
||||
result.top = top;
|
||||
result.right = right;
|
||||
result.bottom = bottom;
|
||||
result.left = left;
|
||||
|
||||
} else if (types.isNumber(value)) {
|
||||
result.top = result.right = result.bottom = result.left = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function layoutParamsComparer(x: CommonLayoutParams, y: CommonLayoutParams): boolean {
|
||||
return x.width === y.width
|
||||
&& x.height === y.height
|
||||
&& x.leftMargin === y.leftMargin
|
||||
&& x.topMargin === y.topMargin
|
||||
&& x.rightMargin === y.rightMargin
|
||||
&& x.bottomMargin === y.bottomMargin
|
||||
&& x.horizontalAlignment === y.horizontalAlignment
|
||||
&& x.verticalAlignment === y.verticalAlignment
|
||||
}
|
||||
|
||||
function onLayoutParamsChanged(data: observable.PropertyChangeData) {
|
||||
var style = <Style>data.object;
|
||||
var layoutParams: CommonLayoutParams = {
|
||||
width: isNaN(style.width) ? -1 : style.width,
|
||||
height: isNaN(style.height) ? -1 : style.height,
|
||||
leftMargin: style.marginLeft,
|
||||
topMargin: style.marginTop,
|
||||
rightMargin: style.marginRight,
|
||||
bottomMargin: style.marginBottom,
|
||||
horizontalAlignment: style.horizontalAlignment,
|
||||
verticalAlignment: style.verticalAlignment
|
||||
};
|
||||
|
||||
style._setValue(nativeLayoutParamsProperty, layoutParams);
|
||||
}
|
||||
|
||||
function onPaddingValueChanged(data: observable.PropertyChangeData) {
|
||||
var style = <Style>data.object;
|
||||
var thickness: Thickness = {
|
||||
top: style.paddingTop,
|
||||
right: style.paddingRight,
|
||||
bottom: style.paddingBottom,
|
||||
left: style.paddingLeft
|
||||
};
|
||||
|
||||
style._setValue(nativePaddingsProperty, thickness);
|
||||
}
|
||||
|
||||
function onPaddingChanged(data: observable.PropertyChangeData) {
|
||||
var thickness = parseThickness(data.newValue);
|
||||
var style = <Style>data.object;
|
||||
|
||||
var valueSource = style._getValueSource(paddingProperty);
|
||||
style._setValue(paddingTopProperty, thickness.top, valueSource);
|
||||
style._setValue(paddingRightProperty, thickness.right, valueSource);
|
||||
style._setValue(paddingBottomProperty, thickness.bottom, valueSource);
|
||||
style._setValue(paddingLeftProperty, thickness.left, valueSource);
|
||||
}
|
||||
|
||||
function onMarginChanged(data: observable.PropertyChangeData) {
|
||||
var thickness = parseThickness(data.newValue);
|
||||
var style = <Style>data.object;
|
||||
|
||||
var valueSource = style._getValueSource(marginProperty);
|
||||
style._setValue(marginTopProperty, thickness.top, valueSource);
|
||||
style._setValue(marginRightProperty, thickness.right, valueSource);
|
||||
style._setValue(marginBottomProperty, thickness.bottom, valueSource);
|
||||
style._setValue(marginLeftProperty, thickness.left, valueSource);
|
||||
}
|
||||
|
||||
function thicknessComparer(x: Thickness, y: Thickness): boolean {
|
||||
return x.left === y.left && x.top === y.top && x.right === y.right && x.bottom === y.bottom;
|
||||
}
|
||||
|
||||
function isWidthHeightValid(value: number): boolean {
|
||||
return isNaN(value) || (value >= 0.0 && isFinite(value));
|
||||
}
|
||||
|
||||
function isMinWidthHeightValid(value: number): boolean {
|
||||
return !isNaN(value) && value >= 0.0 && isFinite(value);
|
||||
}
|
||||
|
||||
function onBackgroundImagePropertyChanged(data: observable.PropertyChangeData) {
|
||||
var view: view.View = (<any>data.object)._view;
|
||||
var style = <Style>data.object;
|
||||
var url: string = data.newValue;
|
||||
|
||||
style._setValue(backgroundImageSourceProperty, undefined, observable.ValueSource.Local);
|
||||
|
||||
if (types.isString(data.newValue)) {
|
||||
var pattern: RegExp = /url\(('|")(.*?)\1\)/;
|
||||
var match = url.match(pattern);
|
||||
if (match && match[2]) {
|
||||
url = match[2];
|
||||
}
|
||||
|
||||
if (utils.isDataURI(url)) {
|
||||
var base64Data = url.split(",")[1];
|
||||
if (types.isDefined(base64Data)) {
|
||||
style._setValue(backgroundImageSourceProperty, imageSource.fromBase64(base64Data), observable.ValueSource.Local);
|
||||
}
|
||||
} else if (utils.isFileOrResourcePath(url)) {
|
||||
style._setValue(backgroundImageSourceProperty, imageSource.fromFileOrResource(url), observable.ValueSource.Local);
|
||||
} else if (url.indexOf("http") !== -1) {
|
||||
if (view) {
|
||||
view["_url"] = url;
|
||||
}
|
||||
imageSource.fromUrl(url).then(r=> {
|
||||
if (view && view["_url"] === url) {
|
||||
style._setValue(backgroundImageSourceProperty, r, observable.ValueSource.Local);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getHandlerInternal(propertyId: number, classInfo: types.ClassInfo): styling.stylers.StylePropertyChangedHandler {
|
||||
var className = classInfo ? classInfo.name : "default";
|
||||
var handlerKey = className + propertyId;
|
||||
|
||||
// try the cache first
|
||||
var result = _handlersCache[handlerKey];
|
||||
if (types.isDefined(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
var propertyHandlers = _registeredHandlers[propertyId];
|
||||
if (noStylingClasses.hasOwnProperty(className) || !propertyHandlers) {
|
||||
// Reached 'no-styling' class or no property handlers are registered for this proeprtyID
|
||||
result = null;
|
||||
}
|
||||
else if (propertyHandlers.hasOwnProperty(className)) {
|
||||
// Found handler for this class
|
||||
result = propertyHandlers[className];
|
||||
}
|
||||
else if (classInfo) {
|
||||
// Check the base class
|
||||
result = getHandlerInternal(propertyId, classInfo.baseClassInfo);
|
||||
}
|
||||
else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
_handlersCache[handlerKey] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
function isVisibilityValid(value: string): boolean {
|
||||
return value === enums.Visibility.visible || value === enums.Visibility.collapse || value === enums.Visibility.collapsed;
|
||||
}
|
||||
|
||||
function onVisibilityChanged(data: observable.PropertyChangeData) {
|
||||
(<any>data.object)._view._isVisibleCache = data.newValue === enums.Visibility.visible;
|
||||
}
|
||||
|
||||
function isPaddingValid(value: number): boolean {
|
||||
return isFinite(value) && !isNaN(value) && value >= 0;
|
||||
}
|
||||
|
||||
function isMarginValid(value: number): boolean {
|
||||
return isFinite(value) && !isNaN(value);
|
||||
}
|
||||
|
||||
function isOpacityValid(value: string): boolean {
|
||||
var parsedValue: number = parseFloat(value);
|
||||
return !isNaN(parsedValue) && 0 <= parsedValue && parsedValue <= 1;
|
||||
}
|
||||
|
||||
export class Style extends observable.DependencyObservable implements styling.Style {
|
||||
private _view: view.View;
|
||||
private _updateCounter = 0;
|
||||
@@ -263,7 +473,7 @@ export class Style extends observable.DependencyObservable implements styling.St
|
||||
super();
|
||||
this._view = parentView;
|
||||
}
|
||||
|
||||
|
||||
public _beginUpdate() {
|
||||
this._updateCounter++;
|
||||
}
|
||||
@@ -274,9 +484,9 @@ export class Style extends observable.DependencyObservable implements styling.St
|
||||
throw new Error("style._endUpdate() called, but no update is in progress.");
|
||||
}
|
||||
if (this._updateCounter === 0) {
|
||||
this._nativeSetters.forEach((newValue, property, map) => { this._applyStyleProperty(property, newValue); });
|
||||
this._nativeSetters.clear();
|
||||
}
|
||||
this._nativeSetters.forEach((newValue, property, map) => { this._applyStyleProperty(property, newValue); });
|
||||
this._nativeSetters.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public _resetCssValues() {
|
||||
@@ -400,9 +610,7 @@ export class Style extends observable.DependencyObservable implements styling.St
|
||||
}
|
||||
}
|
||||
|
||||
export function registerHandler(property: dependencyObservable.Property,
|
||||
handler: styling.stylers.StylePropertyChangedHandler,
|
||||
className?: string) {
|
||||
export function registerHandler(property: dependencyObservable.Property, handler: styling.stylers.StylePropertyChangedHandler, className?: string) {
|
||||
var realClassName = className ? className : "default";
|
||||
|
||||
var handlerRecord = _registeredHandlers[property.id];
|
||||
@@ -422,37 +630,6 @@ export function getHandler(property: dependencyObservable.Property, view: view.V
|
||||
return getHandlerInternal(property.id, types.getClassInfo(view));
|
||||
}
|
||||
|
||||
function getHandlerInternal(propertyId: number, classInfo: types.ClassInfo): styling.stylers.StylePropertyChangedHandler {
|
||||
var className = classInfo ? classInfo.name : "default";
|
||||
var handlerKey = className + propertyId;
|
||||
|
||||
// try the cache first
|
||||
var result = _handlersCache[handlerKey];
|
||||
if (types.isDefined(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
var propertyHandlers = _registeredHandlers[propertyId];
|
||||
if (noStylingClasses.hasOwnProperty(className) || !propertyHandlers) {
|
||||
// Reached 'no-styling' class or no property handlers are registered for this proeprtyID
|
||||
result = null;
|
||||
}
|
||||
else if (propertyHandlers.hasOwnProperty(className)) {
|
||||
// Found handler for this class
|
||||
result = propertyHandlers[className];
|
||||
}
|
||||
else if (classInfo) {
|
||||
// Check the base class
|
||||
result = getHandlerInternal(propertyId, classInfo.baseClassInfo);
|
||||
}
|
||||
else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
_handlersCache[handlerKey] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Property registration
|
||||
export var colorProperty = new styleProperty.Property("color", "color",
|
||||
new observable.PropertyMetadata(undefined, observable.PropertyMetadataSettings.Inheritable, undefined, color.Color.isValid, color.Color.equals),
|
||||
@@ -574,7 +751,7 @@ export var fontWeightProperty = new styleProperty.Property("fontWeight", "font-w
|
||||
new observable.PropertyMetadata(enums.FontWeight.normal, observable.PropertyMetadataSettings.Inheritable, onFontWeightChanged, isFontWeightValid));
|
||||
|
||||
export var fontInternalProperty = new styleProperty.Property("_fontInternal", "_fontInternal",
|
||||
new observable.PropertyMetadata(font.Font.default, observable.PropertyMetadataSettings.AffectsLayout, null, null, font.Font.equals), font.Font.parse);
|
||||
new observable.PropertyMetadata(font.Font.default, AffectsLayout, null, null, font.Font.equals), font.Font.parse);
|
||||
|
||||
function isFontWeightValid(value: string): boolean {
|
||||
return value === enums.FontWeight.normal || value === enums.FontWeight.bold;
|
||||
@@ -632,149 +809,77 @@ function onFontChanged(data: observable.PropertyChangeData) {
|
||||
}
|
||||
|
||||
export var textAlignmentProperty = new styleProperty.Property("textAlignment", "text-align",
|
||||
new observable.PropertyMetadata(undefined, observable.PropertyMetadataSettings.AffectsLayout | observable.PropertyMetadataSettings.Inheritable),
|
||||
converters.textAlignConverter);
|
||||
|
||||
function isWidthHeightValid(value: number): boolean {
|
||||
return isNaN(value) || (value >= 0.0 && isFinite(value));
|
||||
}
|
||||
|
||||
function isMinWidthHeightValid(value: number): boolean {
|
||||
return !isNaN(value) && value >= 0.0 && isFinite(value);
|
||||
}
|
||||
|
||||
export var widthProperty = new styleProperty.Property("width", "width",
|
||||
new observable.PropertyMetadata(
|
||||
Number.NaN, observable.PropertyMetadataSettings.AffectsLayout, null, isWidthHeightValid),
|
||||
converters.numberConverter);
|
||||
|
||||
export var heightProperty = new styleProperty.Property("height", "height",
|
||||
new observable.PropertyMetadata(
|
||||
Number.NaN, observable.PropertyMetadataSettings.AffectsLayout, null, isWidthHeightValid),
|
||||
converters.numberConverter);
|
||||
new observable.PropertyMetadata(undefined, AffectsLayout | observable.PropertyMetadataSettings.Inheritable), converters.textAlignConverter);
|
||||
|
||||
export var minWidthProperty = new styleProperty.Property("minWidth", "min-width",
|
||||
new observable.PropertyMetadata(
|
||||
0, observable.PropertyMetadataSettings.AffectsLayout, null, isMinWidthHeightValid),
|
||||
converters.numberConverter);
|
||||
new observable.PropertyMetadata(0, AffectsLayout, null, isMinWidthHeightValid), converters.numberConverter);
|
||||
|
||||
export var minHeightProperty = new styleProperty.Property("minHeight", "min-height",
|
||||
new observable.PropertyMetadata(
|
||||
0, observable.PropertyMetadataSettings.AffectsLayout, null, isMinWidthHeightValid),
|
||||
converters.numberConverter);
|
||||
new observable.PropertyMetadata(0, AffectsLayout, null, isMinWidthHeightValid), converters.numberConverter);
|
||||
|
||||
function parseThickness(value: any): { top: number; right: number; bottom: number; left: number } {
|
||||
var result = { top: 0, right: 0, bottom: 0, left: 0 };
|
||||
if (types.isString(value)) {
|
||||
var arr = value.split(/[ ,]+/);
|
||||
var top = parseInt(arr[0]);
|
||||
top = isNaN(top) ? 0 : top;
|
||||
// Helper property holding most layout related properties available in CSS.
|
||||
// When layout related properties are set in CSS we chache them and send them to the native view in a single call.
|
||||
export var nativeLayoutParamsProperty = new styleProperty.Property("nativeLayoutParams", "nativeLayoutParams",
|
||||
new observable.PropertyMetadata({
|
||||
width: -1,
|
||||
height: -1,
|
||||
leftMargin: 0,
|
||||
topMargin: 0,
|
||||
rightMargin: 0,
|
||||
bottomMargin: 0,
|
||||
horizontalAlignment: enums.HorizontalAlignment.stretch,
|
||||
verticalAlignment: enums.VerticalAlignment.stretch
|
||||
}, null, null, null, layoutParamsComparer));
|
||||
|
||||
var right = parseInt(arr[1]);
|
||||
right = isNaN(right) ? top : right;
|
||||
// Helper property holding all paddings. When paddings are set through CSS we cache them and send them to the native view in a single call.
|
||||
export var nativePaddingsProperty = new styleProperty.Property("paddingNative", "paddingNative",
|
||||
new observable.PropertyMetadata({ top: 0, right: 0, bottom: 0, left: 0 }, null, null, null, thicknessComparer));
|
||||
|
||||
var bottom = parseInt(arr[2]);
|
||||
bottom = isNaN(bottom) ? top : bottom;
|
||||
export var widthProperty = new styleProperty.Property("width", "width",
|
||||
new observable.PropertyMetadata(Number.NaN, AffectsLayout, onLayoutParamsChanged, isWidthHeightValid), converters.numberConverter);
|
||||
|
||||
var left = parseInt(arr[3]);
|
||||
left = isNaN(left) ? right : left;
|
||||
|
||||
result.top = top;
|
||||
result.right = right;
|
||||
result.bottom = bottom;
|
||||
result.left = left;
|
||||
|
||||
} else if (types.isNumber(value)) {
|
||||
result.top = result.right = result.bottom = result.left = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function onPaddingChanged(data: observable.PropertyChangeData) {
|
||||
var thickness = parseThickness(data.newValue);
|
||||
var style = <Style>data.object;
|
||||
|
||||
style.paddingTop = thickness.top;
|
||||
style.paddingRight = thickness.right;
|
||||
style.paddingBottom = thickness.bottom;
|
||||
style.paddingLeft = thickness.left;
|
||||
}
|
||||
|
||||
function onMarginChanged(data: observable.PropertyChangeData) {
|
||||
var thickness = parseThickness(data.newValue);
|
||||
var style = <Style>data.object;
|
||||
|
||||
style.marginTop = thickness.top;
|
||||
style.marginRight = thickness.right;
|
||||
style.marginBottom = thickness.bottom;
|
||||
style.marginLeft = thickness.left;
|
||||
}
|
||||
export var heightProperty = new styleProperty.Property("height", "height",
|
||||
new observable.PropertyMetadata(Number.NaN, AffectsLayout, onLayoutParamsChanged, isWidthHeightValid), converters.numberConverter);
|
||||
|
||||
export var verticalAlignmentProperty = new styleProperty.Property("verticalAlignment", "vertical-align",
|
||||
new observable.PropertyMetadata(enums.VerticalAlignment.stretch, observable.PropertyMetadataSettings.AffectsLayout));
|
||||
new observable.PropertyMetadata(enums.VerticalAlignment.stretch, AffectsLayout, onLayoutParamsChanged));
|
||||
|
||||
export var horizontalAlignmentProperty = new styleProperty.Property("horizontalAlignment", "horizontal-align",
|
||||
new observable.PropertyMetadata(enums.HorizontalAlignment.stretch, observable.PropertyMetadataSettings.AffectsLayout));
|
||||
new observable.PropertyMetadata(enums.HorizontalAlignment.stretch, AffectsLayout, onLayoutParamsChanged));
|
||||
|
||||
export var marginProperty = new styleProperty.Property("margin", "margin",
|
||||
new observable.PropertyMetadata(null, null, onMarginChanged));
|
||||
|
||||
export var paddingProperty = new styleProperty.Property("padding", "padding",
|
||||
new observable.PropertyMetadata(null, null, onPaddingChanged));
|
||||
export var marginProperty = new styleProperty.Property("margin", "margin", new observable.PropertyMetadata(null, null, onMarginChanged));
|
||||
|
||||
export var marginLeftProperty = new styleProperty.Property("marginLeft", "margin-left",
|
||||
new observable.PropertyMetadata(0, observable.PropertyMetadataSettings.AffectsLayout, null, isMarginValid), converters.numberConverter);
|
||||
new observable.PropertyMetadata(0, AffectsLayout, onLayoutParamsChanged, isMarginValid), converters.numberConverter);
|
||||
|
||||
export var marginRightProperty = new styleProperty.Property("marginRight", "margin-right",
|
||||
new observable.PropertyMetadata(0, observable.PropertyMetadataSettings.AffectsLayout, null, isMarginValid), converters.numberConverter);
|
||||
new observable.PropertyMetadata(0, AffectsLayout, onLayoutParamsChanged, isMarginValid), converters.numberConverter);
|
||||
|
||||
export var marginTopProperty = new styleProperty.Property("marginTop", "margin-top",
|
||||
new observable.PropertyMetadata(0, observable.PropertyMetadataSettings.AffectsLayout, null, isMarginValid), converters.numberConverter);
|
||||
new observable.PropertyMetadata(0, AffectsLayout, onLayoutParamsChanged, isMarginValid), converters.numberConverter);
|
||||
|
||||
export var marginBottomProperty = new styleProperty.Property("marginBottom", "margin-bottom",
|
||||
new observable.PropertyMetadata(0, observable.PropertyMetadataSettings.AffectsLayout, null, isMarginValid), converters.numberConverter);
|
||||
new observable.PropertyMetadata(0, AffectsLayout, onLayoutParamsChanged, isMarginValid), converters.numberConverter);
|
||||
|
||||
export var paddingProperty = new styleProperty.Property("padding", "padding", new observable.PropertyMetadata(null, null, onPaddingChanged));
|
||||
|
||||
export var paddingLeftProperty = new styleProperty.Property("paddingLeft", "padding-left",
|
||||
new observable.PropertyMetadata(0, observable.PropertyMetadataSettings.AffectsLayout, null, isPaddingValid), converters.numberConverter);
|
||||
new observable.PropertyMetadata(0, AffectsLayout, onPaddingValueChanged, isPaddingValid), converters.numberConverter);
|
||||
|
||||
export var paddingRightProperty = new styleProperty.Property("paddingRight", "padding-right",
|
||||
new observable.PropertyMetadata(0, observable.PropertyMetadataSettings.AffectsLayout, null, isPaddingValid), converters.numberConverter);
|
||||
new observable.PropertyMetadata(0, AffectsLayout, onPaddingValueChanged, isPaddingValid), converters.numberConverter);
|
||||
|
||||
export var paddingTopProperty = new styleProperty.Property("paddingTop", "padding-top",
|
||||
new observable.PropertyMetadata(0, observable.PropertyMetadataSettings.AffectsLayout, null, isPaddingValid), converters.numberConverter);
|
||||
new observable.PropertyMetadata(0, AffectsLayout, onPaddingValueChanged, isPaddingValid), converters.numberConverter);
|
||||
|
||||
export var paddingBottomProperty = new styleProperty.Property("paddingBottom", "padding-bottom",
|
||||
new observable.PropertyMetadata(0, observable.PropertyMetadataSettings.AffectsLayout, null, isPaddingValid), converters.numberConverter);
|
||||
|
||||
function isVisibilityValid(value: string): boolean {
|
||||
return value === enums.Visibility.visible || value === enums.Visibility.collapse || value === enums.Visibility.collapsed;
|
||||
}
|
||||
|
||||
function setLayoutInfoVisibility(data: observable.PropertyChangeData) {
|
||||
(<any>data.object)._view._isVisibleCache = (data.newValue === enums.Visibility.visible);
|
||||
}
|
||||
new observable.PropertyMetadata(0, AffectsLayout, onPaddingValueChanged, isPaddingValid), converters.numberConverter);
|
||||
|
||||
export var visibilityProperty = new styleProperty.Property("visibility", "visibility",
|
||||
new observable.PropertyMetadata(enums.Visibility.visible, observable.PropertyMetadataSettings.AffectsLayout, setLayoutInfoVisibility, isVisibilityValid),
|
||||
converters.visibilityConverter);
|
||||
|
||||
function isPaddingValid(value: number): boolean {
|
||||
return isFinite(value) && !isNaN(value) && value >= 0;
|
||||
}
|
||||
|
||||
function isMarginValid(value: number): boolean {
|
||||
return isFinite(value) && !isNaN(value);
|
||||
}
|
||||
|
||||
function isOpacityValid(value: string): boolean {
|
||||
var parsedValue: number = parseFloat(value);
|
||||
return !isNaN(parsedValue) && 0 <= parsedValue && parsedValue <= 1;
|
||||
}
|
||||
new observable.PropertyMetadata(enums.Visibility.visible, AffectsLayout, onVisibilityChanged, isVisibilityValid), converters.visibilityConverter);
|
||||
|
||||
export var opacityProperty = new styleProperty.Property("opacity", "opacity",
|
||||
new observable.PropertyMetadata(1.0, observable.PropertyMetadataSettings.None, undefined, isOpacityValid),
|
||||
converters.opacityConverter);
|
||||
new observable.PropertyMetadata(1.0, observable.PropertyMetadataSettings.None, undefined, isOpacityValid), converters.opacityConverter);
|
||||
|
||||
// register default stylers once all properties are defined.
|
||||
stylers._registerDefaultStylers();
|
||||
@@ -50,7 +50,7 @@ function onBackgroundOrBorderPropertyChanged(v: view.View) {
|
||||
v.android.setBackgroundDrawable(_defaultBackgrounds.get(viewClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DefaultStyler implements definition.stylers.Styler {
|
||||
//Background and borders methods
|
||||
@@ -99,6 +99,94 @@ export class DefaultStyler implements definition.stylers.Styler {
|
||||
(<android.view.View>view._nativeView).setMinimumHeight(0);
|
||||
}
|
||||
|
||||
private static setNativeLayoutParamsProperty(view: view.View, params: style.CommonLayoutParams): void {
|
||||
var nativeView: android.view.View = view._nativeView;
|
||||
|
||||
var lp = <org.nativescript.widgets.CommonLayoutParams>nativeView.getLayoutParams();
|
||||
if (!(lp instanceof org.nativescript.widgets.CommonLayoutParams)) {
|
||||
lp = new org.nativescript.widgets.CommonLayoutParams();
|
||||
}
|
||||
|
||||
lp.leftMargin = params.leftMargin * utils.layout.getDisplayDensity();
|
||||
lp.topMargin = params.topMargin * utils.layout.getDisplayDensity();
|
||||
lp.rightMargin = params.rightMargin * utils.layout.getDisplayDensity();
|
||||
lp.bottomMargin = params.bottomMargin * utils.layout.getDisplayDensity();
|
||||
|
||||
var width = params.width * utils.layout.getDisplayDensity();
|
||||
var height = params.height * utils.layout.getDisplayDensity();
|
||||
|
||||
// If width is not specified set it as WRAP_CONTENT
|
||||
if (width < 0) {
|
||||
width = -2;
|
||||
}
|
||||
|
||||
// If height is not specified set it as WRAP_CONTENT
|
||||
if (lp.height < 0) {
|
||||
lp.height = -2;
|
||||
}
|
||||
|
||||
var gravity = 0;
|
||||
switch (params.horizontalAlignment) {
|
||||
case enums.HorizontalAlignment.left:
|
||||
gravity |= android.view.Gravity.LEFT;
|
||||
break;
|
||||
|
||||
case enums.HorizontalAlignment.center:
|
||||
gravity |= android.view.Gravity.CENTER_HORIZONTAL;
|
||||
break;
|
||||
|
||||
case enums.HorizontalAlignment.right:
|
||||
gravity |= android.view.Gravity.RIGHT;
|
||||
break;
|
||||
|
||||
case enums.HorizontalAlignment.stretch:
|
||||
gravity |= android.view.Gravity.FILL_HORIZONTAL;
|
||||
// If width is not specified set it as MATCH_PARENT
|
||||
if (width < 0) {
|
||||
width = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("Invalid horizontalAlignment value: " + params.horizontalAlignment);
|
||||
}
|
||||
|
||||
switch (params.verticalAlignment) {
|
||||
case enums.VerticalAlignment.top:
|
||||
gravity |= android.view.Gravity.TOP;
|
||||
break;
|
||||
|
||||
case enums.VerticalAlignment.center:
|
||||
gravity |= android.view.Gravity.CENTER_VERTICAL;
|
||||
break;
|
||||
|
||||
case enums.VerticalAlignment.bottom:
|
||||
gravity |= android.view.Gravity.BOTTOM;
|
||||
break;
|
||||
|
||||
case enums.VerticalAlignment.stretch:
|
||||
gravity |= android.view.Gravity.FILL_VERTICAL;
|
||||
// If height is not specified set it as MATCH_PARENT
|
||||
if (height < 0) {
|
||||
height = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("Invalid verticalAlignment value: " + params.verticalAlignment);
|
||||
}
|
||||
|
||||
lp.width = width;
|
||||
lp.height = height;
|
||||
lp.gravity = gravity;
|
||||
nativeView.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
private static resetNativeLayoutParamsProperty(view: view.View, nativeValue: any): void {
|
||||
var nativeView: android.view.View = view._nativeView;
|
||||
nativeView.setLayoutParams(new org.nativescript.widgets.CommonLayoutParams());
|
||||
}
|
||||
|
||||
public static registerHandlers() {
|
||||
style.registerHandler(style.visibilityProperty, new stylersCommon.StylePropertyChangedHandler(
|
||||
DefaultStyler.setVisibilityProperty,
|
||||
@@ -126,6 +214,10 @@ export class DefaultStyler implements definition.stylers.Styler {
|
||||
style.registerHandler(style.borderWidthProperty, borderHandler);
|
||||
style.registerHandler(style.borderColorProperty, borderHandler);
|
||||
style.registerHandler(style.borderRadiusProperty, borderHandler);
|
||||
|
||||
style.registerHandler(style.nativeLayoutParamsProperty, new stylersCommon.StylePropertyChangedHandler(
|
||||
DefaultStyler.setNativeLayoutParamsProperty,
|
||||
DefaultStyler.resetNativeLayoutParamsProperty));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +250,7 @@ export class TextViewStyler implements definition.stylers.Styler {
|
||||
|
||||
if (fontValue.fontSize) {
|
||||
tv.setTextSize(fontValue.fontSize);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tv.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, nativeValue.size);
|
||||
}
|
||||
@@ -368,6 +460,28 @@ export class SearchBarStyler implements definition.stylers.Styler {
|
||||
}
|
||||
}
|
||||
|
||||
export class LayoutBaseStyler implements definition.stylers.Styler {
|
||||
|
||||
//nativePadding methods
|
||||
private static setPaddingNativeProperty(view: view.View, newValue: style.Thickness): void {
|
||||
var left = (newValue.left * utils.layout.getDisplayDensity());
|
||||
var top = (newValue.top * utils.layout.getDisplayDensity());
|
||||
var right = (newValue.right * utils.layout.getDisplayDensity());
|
||||
var bottom = (newValue.bottom * utils.layout.getDisplayDensity());
|
||||
(<android.view.View>view._nativeView).setPadding(left, top, right, bottom);
|
||||
}
|
||||
|
||||
private static resetPaddingNativeProperty(view: view.View, nativeValue: any): void {
|
||||
(<android.view.View>view._nativeView).setPadding(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public static registerHandlers() {
|
||||
style.registerHandler(style.nativePaddingsProperty, new stylersCommon.StylePropertyChangedHandler(
|
||||
LayoutStyler.setPaddingNativeProperty,
|
||||
LayoutStyler.resetPaddingNativeProperty), "Layout");
|
||||
}
|
||||
}
|
||||
|
||||
// Register all styler at the end.
|
||||
export function _registerDefaultStylers() {
|
||||
style.registerNoStylingClass("Frame");
|
||||
@@ -376,4 +490,5 @@ export function _registerDefaultStylers() {
|
||||
ActivityIndicatorStyler.registerHandlers();
|
||||
SegmentedBarStyler.registerHandlers();
|
||||
SearchBarStyler.registerHandlers();
|
||||
LayoutBaseStyler.registerHandlers();
|
||||
}
|
||||
|
||||
@@ -26,9 +26,4 @@ export function greaterThanZero(value: Object): boolean {
|
||||
|
||||
export function notNegative(value: Object): boolean {
|
||||
return (<number>value) >= 0;
|
||||
}
|
||||
|
||||
export function isFiniteNumber(value: Object): boolean {
|
||||
var num = <number>value;
|
||||
return isFinite(num);
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ export module layout {
|
||||
|
||||
export var MEASURED_STATE_TOO_SMALL = 0x01000000;
|
||||
export var MEASURED_STATE_MASK = 0xff000000;
|
||||
export var MEASURED_SIZE_MASK = 0x00ffffff;
|
||||
|
||||
export function getMode(mode: number): string {
|
||||
switch (mode) {
|
||||
|
||||
4
utils/utils.d.ts
vendored
4
utils/utils.d.ts
vendored
@@ -8,6 +8,10 @@
|
||||
* Utility module related to layout.
|
||||
*/
|
||||
module layout {
|
||||
/**
|
||||
* Bits that provide the actual measured size.
|
||||
*/
|
||||
export var MEASURED_SIZE_MASK: number;
|
||||
export var MEASURED_STATE_MASK: number;
|
||||
export var MEASURED_STATE_TOO_SMALL: number;
|
||||
export var UNSPECIFIED: number;
|
||||
|
||||
Reference in New Issue
Block a user