mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
only flex-box left
This commit is contained in:
@@ -14,13 +14,14 @@ import { fontSizeConverter } from "../styling/converters";
|
||||
|
||||
// TODO: Remove this and start using string as source (for android).
|
||||
import { fromFileOrResource, fromBase64, fromUrl } from "image-source";
|
||||
import { isDataURI, isFileOrResourcePath } from "utils/utils";
|
||||
import { isDataURI, isFileOrResourcePath, layout } from "utils/utils";
|
||||
|
||||
export { layout };
|
||||
export * from "./view-base";
|
||||
|
||||
export {
|
||||
GestureTypes, GesturesObserver, GestureEventData,
|
||||
Animation, AnimationPromise,
|
||||
Animation, AnimationPromise,
|
||||
Background, Font, Color
|
||||
}
|
||||
|
||||
@@ -52,67 +53,6 @@ declare module "ui/styling/style" {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace layout {
|
||||
const MODE_SHIFT = 30;
|
||||
const MODE_MASK = 0x3 << MODE_SHIFT;
|
||||
|
||||
export const UNSPECIFIED = 0 << MODE_SHIFT;
|
||||
export const EXACTLY = 1 << MODE_SHIFT;
|
||||
export const AT_MOST = 2 << MODE_SHIFT;
|
||||
|
||||
export const MEASURED_HEIGHT_STATE_SHIFT = 0x00000010; /* 16 */
|
||||
export const MEASURED_STATE_TOO_SMALL = 0x01000000;
|
||||
export const MEASURED_STATE_MASK = 0xff000000;
|
||||
export const MEASURED_SIZE_MASK = 0x00ffffff;
|
||||
|
||||
export function getMeasureSpecMode(spec: number): number {
|
||||
return (spec & MODE_MASK);
|
||||
}
|
||||
|
||||
export function getMeasureSpecSize(spec: number): number {
|
||||
return (spec & ~MODE_MASK);
|
||||
}
|
||||
|
||||
export function getDisplayDensity(): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
export function makeMeasureSpec(size: number, mode: number): number {
|
||||
return (Math.round(size) & ~MODE_MASK) | (mode & MODE_MASK);
|
||||
}
|
||||
|
||||
export function toDevicePixels(value: number): number {
|
||||
return value * getDisplayDensity();
|
||||
}
|
||||
|
||||
export function toDeviceIndependentPixels(value: number): number {
|
||||
return value / getDisplayDensity();
|
||||
}
|
||||
|
||||
export function measureSpecToString(measureSpec: number): string {
|
||||
let mode = getMeasureSpecMode(measureSpec);
|
||||
let size = getMeasureSpecSize(measureSpec);
|
||||
|
||||
let text = "MeasureSpec: ";
|
||||
|
||||
if (mode === UNSPECIFIED) {
|
||||
text += "UNSPECIFIED ";
|
||||
}
|
||||
else if (mode === EXACTLY) {
|
||||
text += "EXACTLY ";
|
||||
}
|
||||
else if (mode === AT_MOST) {
|
||||
text += "AT_MOST ";
|
||||
}
|
||||
else {
|
||||
text += mode + " ";
|
||||
}
|
||||
|
||||
text += size;
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
export function getViewById(view: ViewDefinition, id: string): ViewDefinition {
|
||||
if (!view) {
|
||||
return undefined;
|
||||
@@ -174,6 +114,17 @@ export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator
|
||||
let viewIdCounter = 0;
|
||||
|
||||
export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
// Dynamic properties.
|
||||
left: Length;
|
||||
top: Length;
|
||||
effectiveLeft: number;
|
||||
effectiveTop: number;
|
||||
dock: "left" | "top" | "right" | "bottom";
|
||||
row: number;
|
||||
col: number;
|
||||
rowSpan: number;
|
||||
colSpan: number;
|
||||
|
||||
public static loadedEvent = "loaded";
|
||||
public static unloadedEvent = "unloaded";
|
||||
|
||||
@@ -187,9 +138,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
private _oldRight: number;
|
||||
private _oldBottom: number;
|
||||
|
||||
private _parent: ViewCommon;
|
||||
|
||||
|
||||
private _isLayoutValid: boolean;
|
||||
private _cssType: string;
|
||||
|
||||
@@ -200,7 +148,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
public _isAddedToNativeVisualTree: boolean;
|
||||
public _gestureObservers = {};
|
||||
|
||||
public parent: ViewCommon;
|
||||
// public parent: ViewCommon;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -276,10 +224,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
public eachChild(callback: (child: ViewCommon) => boolean): void {
|
||||
this._eachChildView(callback);
|
||||
}
|
||||
|
||||
private _isEvent(name: string): boolean {
|
||||
return this.constructor && `${name}Event` in this.constructor;
|
||||
}
|
||||
@@ -558,7 +502,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
public isEnabled: boolean;
|
||||
public isUserInteractionEnabled: boolean;
|
||||
|
||||
|
||||
get isLayoutValid(): boolean {
|
||||
return this._isLayoutValid;
|
||||
}
|
||||
@@ -814,8 +757,8 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
}
|
||||
|
||||
private static getMeasureSpec(parentLength: number, parentSpecMode: number, margins: number, childLength: number, stretched: boolean): number {
|
||||
let resultSize = 0;
|
||||
let resultMode = 0;
|
||||
let resultSize: number;
|
||||
let resultMode: number;
|
||||
|
||||
// We want a specific size... let be it.
|
||||
if (childLength >= 0) {
|
||||
@@ -901,8 +844,11 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
|
||||
//@endios
|
||||
|
||||
public eachChild(callback: (child: ViewBase) => boolean): void {
|
||||
this._eachChildView(<any>callback);
|
||||
}
|
||||
|
||||
public _eachChildView(callback: (view: ViewCommon) => boolean) {
|
||||
public _eachChildView(callback: (view: ViewDefinition) => boolean) {
|
||||
//
|
||||
}
|
||||
|
||||
@@ -929,10 +875,12 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
/**
|
||||
* Method is intended to be overridden by inheritors and used as "protected"
|
||||
*/
|
||||
public _addViewCore(view: ViewCommon, atIndex?: number) {
|
||||
if (!view._isAddedToNativeVisualTree) {
|
||||
let nativeIndex = this._childIndexToNativeChildIndex(atIndex);
|
||||
view._isAddedToNativeVisualTree = this._addViewToNativeVisualTree(view, nativeIndex);
|
||||
public _addViewCore(view: ViewBase, atIndex?: number) {
|
||||
if (view instanceof ViewCommon) {
|
||||
if (!view._isAddedToNativeVisualTree) {
|
||||
let nativeIndex = this._childIndexToNativeChildIndex(atIndex);
|
||||
view._isAddedToNativeVisualTree = this._addViewToNativeVisualTree(view, nativeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
super._addViewCore(view, atIndex);
|
||||
@@ -941,12 +889,13 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
/**
|
||||
* Method is intended to be overridden by inheritors and used as "protected"
|
||||
*/
|
||||
public _removeViewCore(view: ViewCommon) {
|
||||
// TODO: Change type from ViewCommon to ViewBase. Probably this
|
||||
// method will need to go to ViewBase class.
|
||||
// Remove the view from the native visual scene first
|
||||
this._removeViewFromNativeVisualTree(view);
|
||||
|
||||
public _removeViewCore(view: ViewBase) {
|
||||
if (view instanceof ViewCommon) {
|
||||
// TODO: Change type from ViewCommon to ViewBase. Probably this
|
||||
// method will need to go to ViewBase class.
|
||||
// Remove the view from the native visual scene first
|
||||
this._removeViewFromNativeVisualTree(view);
|
||||
}
|
||||
super._removeViewCore(view);
|
||||
}
|
||||
|
||||
@@ -1057,18 +1006,18 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
// }
|
||||
}
|
||||
|
||||
export function getLengthEffectiveValue(density: number, param: Length): number {
|
||||
export function getLengthEffectiveValue(param: Length): number {
|
||||
switch (param.unit) {
|
||||
case "px":
|
||||
return Math.round(param.value);
|
||||
|
||||
default:
|
||||
case "dip":
|
||||
return Math.round(density * param.value);
|
||||
return Math.round(layout.getDisplayDensity() * param.value);
|
||||
}
|
||||
}
|
||||
|
||||
function getPercentLengthEffectiveValue(prentAvailableLength: number, density: number, param: PercentLength): number {
|
||||
function getPercentLengthEffectiveValue(prentAvailableLength: number, param: PercentLength): number {
|
||||
switch (param.unit) {
|
||||
case "%":
|
||||
return Math.round(prentAvailableLength * param.value);
|
||||
@@ -1078,7 +1027,7 @@ function getPercentLengthEffectiveValue(prentAvailableLength: number, density: n
|
||||
|
||||
default:
|
||||
case "dip":
|
||||
return Math.round(density * param.value);
|
||||
return Math.round(layout.getDisplayDensity() * param.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1089,17 +1038,17 @@ function updateChildLayoutParams(child: ViewCommon, parent: ViewCommon, density:
|
||||
let parentWidthMeasureSize = layout.getMeasureSpecSize(parentWidthMeasureSpec);
|
||||
let parentWidthMeasureMode = layout.getMeasureSpecMode(parentWidthMeasureSpec);
|
||||
let parentAvailableWidth = parentWidthMeasureMode === layout.UNSPECIFIED ? -1 : parentWidthMeasureSize;
|
||||
style.effectiveWidth = getPercentLengthEffectiveValue(parentAvailableWidth, density, style.width);
|
||||
style.effectiveMarginLeft = getPercentLengthEffectiveValue(parentAvailableWidth, density, style.marginLeft);
|
||||
style.effectiveMarginRight = getPercentLengthEffectiveValue(parentAvailableWidth, density, style.marginRight);
|
||||
style.effectiveWidth = getPercentLengthEffectiveValue(parentAvailableWidth, style.width);
|
||||
style.effectiveMarginLeft = getPercentLengthEffectiveValue(parentAvailableWidth, style.marginLeft);
|
||||
style.effectiveMarginRight = getPercentLengthEffectiveValue(parentAvailableWidth, style.marginRight);
|
||||
|
||||
let parentHeightMeasureSpec = parent._currentHeightMeasureSpec;
|
||||
let parentHeightMeasureSize = layout.getMeasureSpecSize(parentHeightMeasureSpec);
|
||||
let parentHeightMeasureMode = layout.getMeasureSpecMode(parentHeightMeasureSpec);
|
||||
let parentAvailableHeight = parentHeightMeasureMode === layout.UNSPECIFIED ? -1 : parentHeightMeasureSize;
|
||||
style.effectiveHeight = getPercentLengthEffectiveValue(parentAvailableHeight, density, style.height);
|
||||
style.effectiveMarginTop = getPercentLengthEffectiveValue(parentAvailableHeight, density, style.marginTop);
|
||||
style.effectiveMarginBottom = getPercentLengthEffectiveValue(parentAvailableHeight, density, style.marginBottom);
|
||||
style.effectiveHeight = getPercentLengthEffectiveValue(parentAvailableHeight, style.height);
|
||||
style.effectiveMarginTop = getPercentLengthEffectiveValue(parentAvailableHeight, style.marginTop);
|
||||
style.effectiveMarginBottom = getPercentLengthEffectiveValue(parentAvailableHeight, style.marginBottom);
|
||||
}
|
||||
|
||||
interface Length {
|
||||
@@ -1207,7 +1156,7 @@ isEnabledProperty.register(ViewCommon);
|
||||
export const isUserInteractionEnabledProperty = new Property<ViewCommon, boolean>({ name: "isUserInteractionEnabled", defaultValue: true, valueConverter: booleanConverter });
|
||||
isUserInteractionEnabledProperty.register(ViewCommon);
|
||||
|
||||
const zeroLength: Length = { value: 0, unit: "px" };
|
||||
export const zeroLength: Length = { value: 0, unit: "px" };
|
||||
|
||||
export function lengthComparer(x: Length, y: Length): boolean {
|
||||
return x.unit === y.unit && x.value === y.value;
|
||||
@@ -1216,7 +1165,7 @@ export function lengthComparer(x: Length, y: Length): boolean {
|
||||
export const minWidthProperty = new CssProperty<Style, Length>({
|
||||
name: "minWidth", cssName: "min-width", defaultValue: zeroLength, affectsLayout: isIOS, equalityComparer: lengthComparer,
|
||||
valueChanged: (target, newValue) => {
|
||||
target.effectiveMinWidth = getLengthEffectiveValue(layout.getDisplayDensity(), newValue);
|
||||
target.effectiveMinWidth = getLengthEffectiveValue(newValue);
|
||||
}, valueConverter: Length.parse
|
||||
});
|
||||
minWidthProperty.register(Style);
|
||||
@@ -1224,7 +1173,7 @@ minWidthProperty.register(Style);
|
||||
export const minHeightProperty = new CssProperty<Style, Length>({
|
||||
name: "minHeight", cssName: "min-height", defaultValue: zeroLength, affectsLayout: isIOS, equalityComparer: lengthComparer,
|
||||
valueChanged: (target, newValue) => {
|
||||
target.effectiveMinHeight = getLengthEffectiveValue(layout.getDisplayDensity(), newValue);
|
||||
target.effectiveMinHeight = getLengthEffectiveValue(newValue);
|
||||
}, valueConverter: Length.parse
|
||||
});
|
||||
minHeightProperty.register(Style);
|
||||
@@ -1266,7 +1215,7 @@ paddingProperty.register(Style);
|
||||
export const paddingLeftProperty = new CssProperty<Style, Length>({
|
||||
name: "paddingLeft", cssName: "padding-left", defaultValue: zeroLength, affectsLayout: isIOS, equalityComparer: lengthComparer,
|
||||
valueChanged: (target, newValue) => {
|
||||
target.effectivePaddingLeft = getLengthEffectiveValue(layout.getDisplayDensity(), newValue);
|
||||
target.effectivePaddingLeft = getLengthEffectiveValue(newValue);
|
||||
}, valueConverter: Length.parse
|
||||
});
|
||||
paddingLeftProperty.register(Style);
|
||||
@@ -1274,7 +1223,7 @@ paddingLeftProperty.register(Style);
|
||||
export const paddingRightProperty = new CssProperty<Style, Length>({
|
||||
name: "paddingRight", cssName: "padding-right", defaultValue: zeroLength, affectsLayout: isIOS, equalityComparer: lengthComparer,
|
||||
valueChanged: (target, newValue) => {
|
||||
target.effectivePaddingRight = getLengthEffectiveValue(layout.getDisplayDensity(), newValue);
|
||||
target.effectivePaddingRight = getLengthEffectiveValue(newValue);
|
||||
}, valueConverter: Length.parse
|
||||
});
|
||||
paddingRightProperty.register(Style);
|
||||
@@ -1282,7 +1231,7 @@ paddingRightProperty.register(Style);
|
||||
export const paddingTopProperty = new CssProperty<Style, Length>({
|
||||
name: "paddingTop", cssName: "padding-top", defaultValue: zeroLength, affectsLayout: isIOS, equalityComparer: lengthComparer,
|
||||
valueChanged: (target, newValue) => {
|
||||
target.effectivePaddingTop = getLengthEffectiveValue(layout.getDisplayDensity(), newValue);
|
||||
target.effectivePaddingTop = getLengthEffectiveValue(newValue);
|
||||
}, valueConverter: Length.parse
|
||||
});
|
||||
paddingTopProperty.register(Style);
|
||||
@@ -1290,7 +1239,7 @@ paddingTopProperty.register(Style);
|
||||
export const paddingBottomProperty = new CssProperty<Style, Length>({
|
||||
name: "paddingBottom", cssName: "padding-bottom", defaultValue: zeroLength, affectsLayout: isIOS, equalityComparer: lengthComparer,
|
||||
valueChanged: (target, newValue) => {
|
||||
target.effectivePaddingBottom = getLengthEffectiveValue(layout.getDisplayDensity(), newValue);
|
||||
target.effectivePaddingBottom = getLengthEffectiveValue(newValue);
|
||||
}, valueConverter: Length.parse
|
||||
});
|
||||
paddingBottomProperty.register(Style);
|
||||
@@ -1728,7 +1677,7 @@ borderWidthProperty.register(Style);
|
||||
export const borderTopWidthProperty = new CssProperty<Style, Length>({
|
||||
name: "borderTopWidth", cssName: "border-top-width", defaultValue: zeroLength, affectsLayout: isIOS, equalityComparer: lengthComparer,
|
||||
valueChanged: (target, newValue) => {
|
||||
let value = getLengthEffectiveValue(layout.getDisplayDensity(), newValue);
|
||||
let value = getLengthEffectiveValue(newValue);
|
||||
if (!isNonNegativeFiniteNumber(value)) {
|
||||
throw new Error(`border-top-width should be Non-Negative Finite number. Value: ${value}`);
|
||||
}
|
||||
@@ -1742,7 +1691,7 @@ borderTopWidthProperty.register(Style);
|
||||
export const borderRightWidthProperty = new CssProperty<Style, Length>({
|
||||
name: "borderRightWidth", cssName: "border-right-width", defaultValue: zeroLength, affectsLayout: isIOS, equalityComparer: lengthComparer,
|
||||
valueChanged: (target, newValue) => {
|
||||
let value = getLengthEffectiveValue(layout.getDisplayDensity(), newValue);
|
||||
let value = getLengthEffectiveValue(newValue);
|
||||
if (!isNonNegativeFiniteNumber(value)) {
|
||||
throw new Error(`border-right-width should be Non-Negative Finite number. Value: ${value}`);
|
||||
}
|
||||
@@ -1756,7 +1705,7 @@ borderRightWidthProperty.register(Style);
|
||||
export const borderBottomWidthProperty = new CssProperty<Style, Length>({
|
||||
name: "borderBottomWidth", cssName: "border-bottom-width", defaultValue: zeroLength, affectsLayout: isIOS, equalityComparer: lengthComparer,
|
||||
valueChanged: (target, newValue) => {
|
||||
let value = getLengthEffectiveValue(layout.getDisplayDensity(), newValue);
|
||||
let value = getLengthEffectiveValue(newValue);
|
||||
if (!isNonNegativeFiniteNumber(value)) {
|
||||
throw new Error(`border-bottom-width should be Non-Negative Finite number. Value: ${value}`);
|
||||
}
|
||||
@@ -1770,7 +1719,7 @@ borderBottomWidthProperty.register(Style);
|
||||
export const borderLeftWidthProperty = new CssProperty<Style, Length>({
|
||||
name: "borderLeftWidth", cssName: "border-left-width", defaultValue: zeroLength, affectsLayout: isIOS, equalityComparer: lengthComparer,
|
||||
valueChanged: (target, newValue) => {
|
||||
let value = getLengthEffectiveValue(layout.getDisplayDensity(), newValue);
|
||||
let value = getLengthEffectiveValue(newValue);
|
||||
if (!isNonNegativeFiniteNumber(value)) {
|
||||
throw new Error(`border-left-width should be Non-Negative Finite number. Value: ${value}`);
|
||||
}
|
||||
@@ -1970,4 +1919,4 @@ export const fontProperty = new ShorthandProperty<Style>({
|
||||
]
|
||||
}
|
||||
})
|
||||
fontProperty.register(Style);
|
||||
fontProperty.register(Style);
|
||||
@@ -1,23 +1,25 @@
|
||||
import { PercentLength, Length, Point, CustomLayoutView as CustomLayoutViewDefinition } from "ui/core/view";
|
||||
import { ad } from "ui/styling/background";
|
||||
import { ad as androidBackground } from "ui/styling/background";
|
||||
import {
|
||||
ViewCommon, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty, visibilityProperty, opacityProperty, minWidthProperty, minHeightProperty,
|
||||
ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty, visibilityProperty, opacityProperty, minWidthProperty, minHeightProperty,
|
||||
widthProperty, heightProperty, marginLeftProperty, marginTopProperty,
|
||||
marginRightProperty, marginBottomProperty, horizontalAlignmentProperty, verticalAlignmentProperty,
|
||||
paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty,
|
||||
rotateProperty, scaleXProperty, scaleYProperty,
|
||||
translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty,
|
||||
layout, Background, GestureTypes, GestureEventData, applyNativeSetters, Property,
|
||||
Background, GestureTypes, GestureEventData, applyNativeSetters, Property,
|
||||
traceEnabled, traceWrite, traceCategories, traceNotifyEvent
|
||||
} from "./view-common";
|
||||
|
||||
import { } from "utils/utils";
|
||||
|
||||
export * from "./view-common";
|
||||
|
||||
let flexbox;
|
||||
|
||||
const ANDROID = "_android";
|
||||
const NATIVE_VIEW = "_nativeView";
|
||||
const VIEW_GROUP = "_viewGroup";
|
||||
let density = -1;
|
||||
|
||||
// TODO: Move this class into widgets.
|
||||
@Interfaces([android.view.View.OnTouchListener])
|
||||
@@ -651,9 +653,8 @@ export class View extends ViewCommon {
|
||||
if (value instanceof android.graphics.drawable.Drawable) {
|
||||
this.nativeView.setBackground(value);
|
||||
} else {
|
||||
ad.onBackgroundOrBorderPropertyChanged(this);
|
||||
androidBackground.onBackgroundOrBorderPropertyChanged(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
tns-core-modules/ui/core/view.d.ts
vendored
3
tns-core-modules/ui/core/view.d.ts
vendored
@@ -17,6 +17,9 @@ declare module "ui/core/view" {
|
||||
|
||||
export * from "ui/core/view-base";
|
||||
|
||||
export const zeroLength: Length;
|
||||
export function getLengthEffectiveValue(param: Length): number;
|
||||
|
||||
/**
|
||||
* Gets a child view by id.
|
||||
* @param view - The parent (container) view of the view to look for.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AbsoluteLayout as AbsoluteLayoutDefinition } from "ui/layouts/absolute-layout";
|
||||
import { LayoutBase, View, Property, Length, lengthComparer } from "ui/layouts/layout-base";
|
||||
import { LayoutBase, View, Property, Length, lengthComparer, zeroLength, getLengthEffectiveValue } from "ui/layouts/layout-base";
|
||||
|
||||
export * from "ui/layouts/layout-base";
|
||||
|
||||
@@ -52,11 +52,10 @@ export class AbsoluteLayoutBase extends LayoutBase implements AbsoluteLayoutDefi
|
||||
}
|
||||
}
|
||||
|
||||
export const zeroLenth: Length = { value: 0, unit: "px" };
|
||||
|
||||
export const leftProperty = new Property<View, Length>({
|
||||
name: "left", defaultValue: zeroLenth,
|
||||
name: "left", defaultValue: zeroLength,
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
target.effectiveLeft = getLengthEffectiveValue(newValue);
|
||||
const layout = target.parent;
|
||||
if (layout instanceof AbsoluteLayoutBase) {
|
||||
layout.onLeftChanged(target, oldValue, newValue);
|
||||
@@ -66,8 +65,9 @@ export const leftProperty = new Property<View, Length>({
|
||||
leftProperty.register(AbsoluteLayoutBase);
|
||||
|
||||
export const topProperty = new Property<View, Length>({
|
||||
name: "top", defaultValue: zeroLenth,
|
||||
name: "top", defaultValue: zeroLength,
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
target.effectiveTop = getLengthEffectiveValue(newValue);
|
||||
const layout = target.parent;
|
||||
if (layout instanceof AbsoluteLayoutBase) {
|
||||
layout.onTopChanged(target, oldValue, newValue);
|
||||
|
||||
@@ -1,12 +1,39 @@
|
||||
import { AbsoluteLayoutBase, leftProperty, topProperty, Length, zeroLength } from "./absolute-layout-common";
|
||||
import { AbsoluteLayoutBase, View, leftProperty, topProperty, Length, zeroLength } from "./absolute-layout-common";
|
||||
|
||||
export * from "./absolute-layout-common";
|
||||
|
||||
function setNativeProperty(data: PropertyChangeData, setter: (lp: org.nativescript.widgets.CommonLayoutParams) => void) {
|
||||
var view = data.object;
|
||||
// define native getter and setter for leftProperty.
|
||||
let leftDescriptor: TypedPropertyDescriptor<Length> = {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
get: () => zeroLength,
|
||||
set: function (this: View, value: Length) {
|
||||
setNativeProperty(this, (lp) => lp.left = this.effectiveLeft);
|
||||
}
|
||||
}
|
||||
|
||||
// define native getter and setter for topProperty.
|
||||
let topDescriptor: TypedPropertyDescriptor<Length> = {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
get: () => zeroLength,
|
||||
set: function (this: View, value: Length) {
|
||||
setNativeProperty(this, (lp) => lp.top = this.effectiveTop);
|
||||
}
|
||||
}
|
||||
|
||||
// register native properties on View type.
|
||||
Object.defineProperties(View, {
|
||||
[leftProperty.native]: leftDescriptor,
|
||||
[topProperty.native]: topDescriptor
|
||||
});
|
||||
|
||||
function setNativeProperty(view: View, setter: (lp: org.nativescript.widgets.CommonLayoutParams) => void) {
|
||||
if (view instanceof View) {
|
||||
var nativeView: android.view.View = view._nativeView;
|
||||
var lp = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams();
|
||||
const nativeView: android.view.View = view._nativeView;
|
||||
const lp = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams();
|
||||
if (lp instanceof org.nativescript.widgets.CommonLayoutParams) {
|
||||
setter(lp);
|
||||
nativeView.setLayoutParams(lp);
|
||||
@@ -14,17 +41,6 @@ function setNativeProperty(data: PropertyChangeData, setter: (lp: org.nativescri
|
||||
}
|
||||
}
|
||||
|
||||
function setNativeLeftProperty(data: PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.left = data.newValue * utils.layout.getDisplayDensity(); });
|
||||
}
|
||||
|
||||
function setNativeTopProperty(data: PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.top = data.newValue * utils.layout.getDisplayDensity(); });
|
||||
}
|
||||
|
||||
(<PropertyMetadata>common.AbsoluteLayout.leftProperty.metadata).onSetNativeValue = setNativeLeftProperty;
|
||||
(<PropertyMetadata>common.AbsoluteLayout.topProperty.metadata).onSetNativeValue = setNativeTopProperty;
|
||||
|
||||
export class AbsoluteLayout extends AbsoluteLayoutBase {
|
||||
|
||||
private _layout: org.nativescript.widgets.AbsoluteLayout;
|
||||
@@ -40,13 +56,4 @@ export class AbsoluteLayout extends AbsoluteLayoutBase {
|
||||
public _createUI() {
|
||||
this._layout = new org.nativescript.widgets.AbsoluteLayout(this._context);
|
||||
}
|
||||
|
||||
-------------------------
|
||||
This should be defined with Object.DefineProperty on a View type........
|
||||
get [leftProperty.native](): Length {
|
||||
return zeroLength;
|
||||
}
|
||||
set [leftProperty.native](value: Length) {
|
||||
return zeroLength;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,47 @@
|
||||
import utils = require("utils/utils");
|
||||
import common = require("./absolute-layout-common");
|
||||
import {View} from "ui/core/view";
|
||||
import {CommonLayoutParams, nativeLayoutParamsProperty} from "ui/styling/style";
|
||||
import { AbsoluteLayoutBase, View, layout, Length } from "./absolute-layout-common";
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
export * from "./absolute-layout-common";
|
||||
|
||||
export class AbsoluteLayout extends common.AbsoluteLayout {
|
||||
protected onLeftChanged(view: View, oldValue: number, newValue: number) {
|
||||
export class AbsoluteLayout extends AbsoluteLayoutBase {
|
||||
|
||||
onLeftChanged(view: View, oldValue: Length, newValue: Length) {
|
||||
this.requestLayout();
|
||||
}
|
||||
|
||||
protected onTopChanged(view: View, oldValue: number, newValue: number) {
|
||||
onTopChanged(view: View, oldValue: Length, newValue: Length) {
|
||||
this.requestLayout();
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
AbsoluteLayout.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
let measureWidth = 0;
|
||||
let measureHeight = 0;
|
||||
|
||||
let width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
let widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
let height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
let heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
let childMeasureSpec = utils.layout.makeMeasureSpec(0, utils.layout.UNSPECIFIED);
|
||||
let density = utils.layout.getDisplayDensity();
|
||||
|
||||
const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
const childMeasureSpec = layout.makeMeasureSpec(0, layout.UNSPECIFIED);
|
||||
|
||||
this.eachLayoutChild((child, last) => {
|
||||
let childSize = View.measureChild(this, child, childMeasureSpec, childMeasureSpec);
|
||||
measureWidth = Math.max(measureWidth, AbsoluteLayout.getLeft(child) * density + childSize.measuredWidth);
|
||||
measureHeight = Math.max(measureHeight, AbsoluteLayout.getTop(child) * density + childSize.measuredHeight);
|
||||
measureWidth = Math.max(measureWidth, child.effectiveLeft + childSize.measuredWidth);
|
||||
measureHeight = Math.max(measureHeight, child.effectiveTop + childSize.measuredHeight);
|
||||
});
|
||||
|
||||
measureWidth += (this.borderLeftWidth + this.paddingLeft + this.paddingRight + this.borderRightWidth) * density;
|
||||
measureHeight += (this.borderTopWidth + this.paddingTop + this.paddingBottom + this.borderBottomWidth) * density;
|
||||
const style = this.style;
|
||||
|
||||
measureWidth = Math.max(measureWidth, this.minWidth * density);
|
||||
measureHeight = Math.max(measureHeight, this.minHeight * density);
|
||||
measureWidth += style.effectiveBorderLeftWidth + style.effectivePaddingLeft + style.effectivePaddingRight + style.effectiveBorderRightWidth;
|
||||
measureHeight += style.effectiveBorderTopWidth + style.effectivePaddingTop + style.effectivePaddingBottom + style.effectiveBorderBottomWidth;
|
||||
|
||||
let widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
let heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
measureWidth = Math.max(measureWidth, style.effectiveMinWidth);
|
||||
measureHeight = Math.max(measureHeight, style.effectiveMinHeight);
|
||||
|
||||
const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
@@ -51,21 +49,18 @@ export class AbsoluteLayout extends common.AbsoluteLayout {
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
super.onLayout(left, top, right, bottom);
|
||||
|
||||
let density = utils.layout.getDisplayDensity();
|
||||
const style = this.style;
|
||||
this.eachLayoutChild((child, last) => {
|
||||
let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
|
||||
|
||||
let childWidth = child.getMeasuredWidth();
|
||||
let childHeight = child.getMeasuredHeight();
|
||||
const childWidth = child.getMeasuredWidth();
|
||||
const childHeight = child.getMeasuredHeight();
|
||||
|
||||
let childLeft = (this.borderLeftWidth + this.paddingLeft + AbsoluteLayout.getLeft(child)) * density;
|
||||
let childTop = (this.borderTopWidth + this.paddingTop + AbsoluteLayout.getTop(child)) * density;
|
||||
let childRight = childLeft + childWidth + (lp.leftMargin + lp.rightMargin) * density;
|
||||
let childBottom = childTop + childHeight + (lp.topMargin + lp.bottomMargin) * density;
|
||||
const childLeft = style.effectiveBorderLeftWidth + style.effectivePaddingLeft + child.effectiveLeft;
|
||||
const childTop = style.effectiveBorderTopWidth + style.effectivePaddingTop + child.effectiveTop;
|
||||
const childRight = childLeft + childWidth + style.effectiveMarginLeft + style.effectiveMarginRight;
|
||||
const childBottom = childTop + childHeight + style.effectiveMarginTop + style.effectiveMarginBottom;
|
||||
|
||||
View.layoutChild(this, child, childLeft, childTop, childRight, childBottom);
|
||||
});
|
||||
|
||||
AbsoluteLayout.restoreOriginalParams(this);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,5 @@
|
||||
import definition = require("ui/layouts/dock-layout");
|
||||
import platform = require("platform");
|
||||
import {Dock} from "ui/enums";
|
||||
import {LayoutBase} from "ui/layouts/layout-base";
|
||||
import {View} from "ui/core/view";
|
||||
import {PropertyMetadata} from "ui/core/proxy";
|
||||
import {Property, PropertyChangeData, PropertyMetadataSettings} from "ui/core/dependency-observable";
|
||||
import {registerSpecialProperty} from "ui/builder/special-properties";
|
||||
|
||||
// on Android we explicitly set propertySettings to None because android will invalidate its layout (skip unnecessary native call).
|
||||
var AffectsLayout = platform.device.os === platform.platformNames.android ? PropertyMetadataSettings.None : PropertyMetadataSettings.AffectsLayout;
|
||||
|
||||
function isDockValid(value: any): boolean {
|
||||
return value === Dock.left || value === Dock.top || value === Dock.right || value === Dock.bottom;
|
||||
}
|
||||
import { DockLayout as DockLayoutDefinition } from "ui/layouts/dock-layout";
|
||||
import { LayoutBase, View, Property, isIOS, booleanConverter } from "ui/layouts/layout-base";
|
||||
|
||||
function validateArgs(element: View): View {
|
||||
if (!element) {
|
||||
@@ -21,44 +8,52 @@ function validateArgs(element: View): View {
|
||||
return element;
|
||||
}
|
||||
|
||||
registerSpecialProperty("dock", (instance, propertyValue) => {
|
||||
DockLayout.setDock(instance, propertyValue);
|
||||
});
|
||||
export * from "ui/layouts/layout-base";
|
||||
|
||||
export class DockLayout extends LayoutBase implements definition.DockLayout {
|
||||
declare module "ui/core/view" {
|
||||
interface View {
|
||||
dock: "left" | "top" | "right" | "bottom";
|
||||
}
|
||||
}
|
||||
|
||||
private static onDockPropertyChanged(data: PropertyChangeData) {
|
||||
var view = data.object;
|
||||
if (view instanceof View) {
|
||||
var layout = view.parent;
|
||||
if (layout instanceof DockLayout) {
|
||||
layout.onDockChanged(view, data.oldValue, data.newValue);
|
||||
}
|
||||
}
|
||||
View.prototype.dock = "left";
|
||||
|
||||
export class DockLayoutBase extends LayoutBase implements DockLayoutDefinition {
|
||||
|
||||
public static getDock(element: View): "left" | "top" | "right" | "bottom" {
|
||||
return validateArgs(element).dock;
|
||||
}
|
||||
|
||||
public static dockProperty = new Property(
|
||||
"dock", "DockLayout", new PropertyMetadata(Dock.left, undefined, DockLayout.onDockPropertyChanged, isDockValid));
|
||||
|
||||
public static stretchLastChildProperty = new Property(
|
||||
"stretchLastChild", "DockLayout", new PropertyMetadata(true, AffectsLayout));
|
||||
|
||||
public static getDock(element: View): string {
|
||||
return validateArgs(element)._getValue(DockLayout.dockProperty);
|
||||
public static setDock(element: View, value: "left" | "top" | "right" | "bottom"): void {
|
||||
validateArgs(element).dock = value;
|
||||
}
|
||||
|
||||
public static setDock(element: View, value: string): void {
|
||||
validateArgs(element)._setValue(DockLayout.dockProperty, value);
|
||||
}
|
||||
public stretchLastChild: boolean;
|
||||
|
||||
get stretchLastChild(): boolean {
|
||||
return this._getValue(DockLayout.stretchLastChildProperty);
|
||||
}
|
||||
set stretchLastChild(value: boolean) {
|
||||
this._setValue(DockLayout.stretchLastChildProperty, value);
|
||||
}
|
||||
|
||||
protected onDockChanged(view: View, oldValue: number, newValue: number) {
|
||||
public onDockChanged(view: View, oldValue: "left" | "top" | "right" | "bottom", newValue: "left" | "top" | "right" | "bottom") {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const dockProperty = new Property<View, "left" | "top" | "right" | "bottom">({
|
||||
name: "dock", defaultValue: "left", valueChanged: (target, oldValue, newValue) => {
|
||||
if (target instanceof View) {
|
||||
const layout = target.parent;
|
||||
if (layout instanceof DockLayoutBase) {
|
||||
layout.onDockChanged(target, oldValue, newValue);
|
||||
}
|
||||
}
|
||||
}, valueConverter: (v) => {
|
||||
if (v === "left" || v === "top" || v === "right" || v === "bottom") {
|
||||
return <"left" | "top" | "right" | "bottom">v;
|
||||
}
|
||||
|
||||
throw new Error(`Invalid value for dock property: ${v}`);
|
||||
}
|
||||
});
|
||||
dockProperty.register(DockLayoutBase);
|
||||
|
||||
export const stretchLastChildProperty = new Property<DockLayoutBase, boolean>({
|
||||
name: "stretchLastChild", defaultValue: true, affectsLayout: isIOS, valueConverter: booleanConverter
|
||||
});
|
||||
stretchLastChildProperty.register(DockLayoutBase);
|
||||
@@ -1,32 +1,36 @@
|
||||
import common = require("./dock-layout-common");
|
||||
import {Dock} from "ui/enums";
|
||||
import {View} from "ui/core/view";
|
||||
import {PropertyMetadata} from "ui/core/proxy";
|
||||
import {PropertyChangeData} from "ui/core/dependency-observable";
|
||||
import { DockLayoutBase, View, dockProperty, stretchLastChildProperty } from "./dock-layout-common";
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
export * from "./dock-layout-common";
|
||||
|
||||
function setNativeDockProperty(data: PropertyChangeData) {
|
||||
var view = data.object;
|
||||
if (view instanceof View) {
|
||||
var nativeView: android.view.View = view._nativeView;
|
||||
var lp = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams();
|
||||
// define native getter and setter for topProperty.
|
||||
let dockDescriptor: TypedPropertyDescriptor<"left" | "top" | "right" | "bottom"> = {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
get: () => "left",
|
||||
set: function (this: View, value: "left" | "top" | "right" | "bottom") {
|
||||
const nativeView: android.view.View = this._nativeView;
|
||||
const lp = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams();
|
||||
if (lp instanceof org.nativescript.widgets.CommonLayoutParams) {
|
||||
switch (data.newValue) {
|
||||
case Dock.left:
|
||||
switch (value) {
|
||||
case "left":
|
||||
lp.dock = org.nativescript.widgets.Dock.left;
|
||||
break;
|
||||
case Dock.top:
|
||||
|
||||
case "top":
|
||||
lp.dock = org.nativescript.widgets.Dock.top;
|
||||
break;
|
||||
case Dock.right:
|
||||
|
||||
case "right":
|
||||
lp.dock = org.nativescript.widgets.Dock.right;
|
||||
break;
|
||||
case Dock.bottom:
|
||||
|
||||
case "bottom":
|
||||
lp.dock = org.nativescript.widgets.Dock.bottom;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("Invalid dock value: " + data.newValue + " on element: " + view);
|
||||
throw new Error(`Invalid value for dock property: ${value}`);
|
||||
}
|
||||
|
||||
nativeView.setLayoutParams(lp);
|
||||
@@ -34,17 +38,12 @@ function setNativeDockProperty(data: PropertyChangeData) {
|
||||
}
|
||||
}
|
||||
|
||||
(<PropertyMetadata>common.DockLayout.dockProperty.metadata).onSetNativeValue = setNativeDockProperty;
|
||||
// register native properties on View type.
|
||||
Object.defineProperties(View, {
|
||||
[dockProperty.native]: dockDescriptor
|
||||
});
|
||||
|
||||
function setNativeStretchLastChildProperty(data: PropertyChangeData) {
|
||||
let dockLayout = <DockLayout>data.object;
|
||||
let nativeView = dockLayout._nativeView;
|
||||
nativeView.setStretchLastChild(data.newValue);
|
||||
}
|
||||
|
||||
(<PropertyMetadata>common.DockLayout.stretchLastChildProperty.metadata).onSetNativeValue = setNativeStretchLastChildProperty;
|
||||
|
||||
export class DockLayout extends common.DockLayout {
|
||||
export class DockLayout extends DockLayoutBase {
|
||||
|
||||
private _layout: org.nativescript.widgets.DockLayout;
|
||||
|
||||
@@ -59,4 +58,11 @@ export class DockLayout extends common.DockLayout {
|
||||
public _createUI() {
|
||||
this._layout = new org.nativescript.widgets.DockLayout(this._context);
|
||||
}
|
||||
|
||||
get [stretchLastChildProperty.native](): boolean {
|
||||
return false;
|
||||
}
|
||||
set [stretchLastChildProperty.native](value: boolean) {
|
||||
this._layout.setStretchLastChild(value);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,10 @@
|
||||
declare module "ui/layouts/dock-layout" {
|
||||
import {LayoutBase} from "ui/layouts/layout-base";
|
||||
import {View} from "ui/core/view";
|
||||
import {Property} from "ui/core/dependency-observable";
|
||||
import { LayoutBase, View, Property } from "ui/layouts/layout-base";
|
||||
|
||||
/**
|
||||
* A Layout that arranges its children at its outer edges, and allows its last child to take up the remaining space.
|
||||
*/
|
||||
class DockLayout extends LayoutBase {
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the dock property.
|
||||
*/
|
||||
public static dockProperty: Property;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the stretchLastChild property of each DockLayout instance.
|
||||
*/
|
||||
public static stretchLastChildProperty: Property;
|
||||
|
||||
/**
|
||||
* Gets the value of the Left property from a given View.
|
||||
*/
|
||||
@@ -34,4 +21,14 @@
|
||||
*/
|
||||
stretchLastChild: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the dock property.
|
||||
*/
|
||||
export const dockProperty: Property<DockLayout, "left" | "top" | "right" | "bottom">;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the stretchLastChild property of each DockLayout instance.
|
||||
*/
|
||||
export const stretchLastChildProperty: Property<DockLayout, boolean>;
|
||||
}
|
||||
@@ -1,65 +1,61 @@
|
||||
import utils = require("utils/utils");
|
||||
import common = require("./dock-layout-common");
|
||||
import {CommonLayoutParams, nativeLayoutParamsProperty} from "ui/styling/style";
|
||||
import {Dock} from "ui/enums";
|
||||
import {View} from "ui/core/view";
|
||||
import { DockLayoutBase, View, dockProperty, stretchLastChildProperty, layout } from "./dock-layout-common";
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
export * from "./dock-layout-common";
|
||||
|
||||
export class DockLayout extends common.DockLayout {
|
||||
export class DockLayout extends DockLayoutBase {
|
||||
|
||||
protected onDockChanged(view: View, oldValue: number, newValue: number) {
|
||||
public onDockChanged(view: View, oldValue: "left" | "top" | "right" | "bottom", newValue: "left" | "top" | "right" | "bottom") {
|
||||
this.requestLayout();
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
DockLayout.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
var measureWidth = 0;
|
||||
var measureHeight = 0;
|
||||
let measureWidth = 0;
|
||||
let measureHeight = 0;
|
||||
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
var density = utils.layout.getDisplayDensity();
|
||||
const style = this.style;
|
||||
const horizontalPaddingsAndMargins = style.effectivePaddingLeft + style.effectivePaddingRight + style.effectiveBorderLeftWidth + style.effectiveBorderRightWidth;
|
||||
const verticalPaddingsAndMargins = style.effectivePaddingTop + style.effectivePaddingBottom + style.effectiveBorderTopWidth + style.effectiveBorderBottomWidth;
|
||||
|
||||
let remainingWidth = widthMode === layout.UNSPECIFIED ? Number.MAX_VALUE : width - horizontalPaddingsAndMargins;
|
||||
let remainingHeight = heightMode === layout.UNSPECIFIED ? Number.MAX_VALUE : height - verticalPaddingsAndMargins;
|
||||
|
||||
var remainingWidth = widthMode === utils.layout.UNSPECIFIED ? Number.MAX_VALUE : width - ((this.borderLeftWidth + this.paddingLeft + this.paddingRight + this.borderRightWidth) * density);
|
||||
var remainingHeight = heightMode === utils.layout.UNSPECIFIED ? Number.MAX_VALUE : height - ((this.borderTopWidth + this.paddingTop + this.paddingBottom + this.borderBottomWidth) * density);
|
||||
|
||||
var tempHeight: number = 0;
|
||||
var tempWidth: number = 0;
|
||||
var childWidthMeasureSpec: number;
|
||||
var childHeightMeasureSpec: number;
|
||||
let tempHeight: number = 0;
|
||||
let tempWidth: number = 0;
|
||||
let childWidthMeasureSpec: number;
|
||||
let childHeightMeasureSpec: number;
|
||||
|
||||
this.eachLayoutChild((child, last) => {
|
||||
if (this.stretchLastChild && last) {
|
||||
childWidthMeasureSpec = utils.layout.makeMeasureSpec(remainingWidth, widthMode);
|
||||
childHeightMeasureSpec = utils.layout.makeMeasureSpec(remainingHeight, heightMode);
|
||||
childWidthMeasureSpec = layout.makeMeasureSpec(remainingWidth, widthMode);
|
||||
childHeightMeasureSpec = layout.makeMeasureSpec(remainingHeight, heightMode);
|
||||
}
|
||||
else {
|
||||
// Measure children with AT_MOST even if our mode is EXACT
|
||||
childWidthMeasureSpec = utils.layout.makeMeasureSpec(remainingWidth, widthMode === utils.layout.EXACTLY ? utils.layout.AT_MOST : widthMode);
|
||||
childHeightMeasureSpec = utils.layout.makeMeasureSpec(remainingHeight, heightMode === utils.layout.EXACTLY ? utils.layout.AT_MOST : heightMode);
|
||||
childWidthMeasureSpec = layout.makeMeasureSpec(remainingWidth, widthMode === layout.EXACTLY ? layout.AT_MOST : widthMode);
|
||||
childHeightMeasureSpec = layout.makeMeasureSpec(remainingHeight, heightMode === layout.EXACTLY ? layout.AT_MOST : heightMode);
|
||||
}
|
||||
|
||||
let childSize = View.measureChild(this, child, childWidthMeasureSpec, childHeightMeasureSpec);
|
||||
let dock = DockLayout.getDock(child);
|
||||
|
||||
switch (dock) {
|
||||
case Dock.top:
|
||||
case Dock.bottom:
|
||||
switch (child.dock) {
|
||||
case "top":
|
||||
case "bottom":
|
||||
remainingHeight = Math.max(0, remainingHeight - childSize.measuredHeight);
|
||||
tempHeight += childSize.measuredHeight;
|
||||
measureWidth = Math.max(measureWidth, tempWidth + childSize.measuredWidth);
|
||||
measureHeight = Math.max(measureHeight, tempHeight);
|
||||
break;
|
||||
|
||||
case Dock.left:
|
||||
case Dock.right:
|
||||
case "left":
|
||||
case "right":
|
||||
default:
|
||||
remainingWidth = Math.max(0, remainingWidth - childSize.measuredWidth);
|
||||
tempWidth += childSize.measuredWidth;
|
||||
@@ -69,14 +65,14 @@ export class DockLayout extends common.DockLayout {
|
||||
}
|
||||
});
|
||||
|
||||
measureWidth += (this.borderLeftWidth + this.paddingLeft + this.paddingRight + this.borderRightWidth) * density;
|
||||
measureHeight += (this.borderTopWidth + this.paddingTop + this.paddingBottom + this.borderBottomWidth) * density;
|
||||
measureWidth += horizontalPaddingsAndMargins;
|
||||
measureHeight += verticalPaddingsAndMargins;
|
||||
|
||||
measureWidth = Math.max(measureWidth, this.minWidth * density);
|
||||
measureHeight = Math.max(measureHeight, this.minHeight * density);
|
||||
measureWidth = Math.max(measureWidth, style.effectiveMinWidth);
|
||||
measureHeight = Math.max(measureHeight, style.effectiveMinHeight);
|
||||
|
||||
var widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
var heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
@@ -84,32 +80,34 @@ export class DockLayout extends common.DockLayout {
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
super.onLayout(left, top, right, bottom);
|
||||
|
||||
var density = utils.layout.getDisplayDensity();
|
||||
const style = this.style;
|
||||
const horizontalPaddingsAndMargins = style.effectivePaddingLeft + style.effectivePaddingRight + style.effectiveBorderLeftWidth + style.effectiveBorderRightWidth;
|
||||
const verticalPaddingsAndMargins = style.effectivePaddingTop + style.effectivePaddingBottom + style.effectiveBorderTopWidth + style.effectiveBorderBottomWidth;
|
||||
|
||||
var childLeft = (this.borderLeftWidth + this.paddingLeft) * density;
|
||||
var childTop = (this.borderTopWidth + this.paddingTop) * density;
|
||||
let childLeft = style.effectiveBorderLeftWidth + style.effectivePaddingLeft;
|
||||
let childTop = style.effectiveBorderTopWidth + style.effectivePaddingTop;
|
||||
|
||||
var x = childLeft;
|
||||
var y = childTop;
|
||||
let x = childLeft;
|
||||
let y = childTop;
|
||||
|
||||
var remainingWidth = Math.max(0, right - left - ((this.borderLeftWidth + this.paddingLeft + this.paddingRight + this.borderRightWidth) * density));
|
||||
var remainingHeight = Math.max(0, bottom - top - ((this.borderTopWidth + this.paddingTop + this.paddingBottom + this.borderBottomWidth) * density));
|
||||
let remainingWidth = Math.max(0, right - left - horizontalPaddingsAndMargins);
|
||||
let remainingHeight = Math.max(0, bottom - top - verticalPaddingsAndMargins);
|
||||
|
||||
this.eachLayoutChild((child, last) => {
|
||||
let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
|
||||
let childStlye = child.style;
|
||||
|
||||
let childWidth = child.getMeasuredWidth() + childStlye.effectiveMarginLeft + childStlye.effectiveMarginRight;
|
||||
let childHeight = child.getMeasuredHeight() + childStlye.effectiveMarginTop + childStlye.effectiveMarginBottom;
|
||||
|
||||
let childWidth = child.getMeasuredWidth() + (lp.leftMargin + lp.rightMargin) * density;
|
||||
let childHeight = child.getMeasuredHeight() + (lp.topMargin + lp.bottomMargin) * density;
|
||||
|
||||
if (last && this.stretchLastChild) {
|
||||
// Last child with stretch - give it all the space and return;
|
||||
View.layoutChild(this, child, x, y, x + remainingWidth, y + remainingHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let dock = DockLayout.getDock(child);
|
||||
switch (dock) {
|
||||
case Dock.top:
|
||||
case "top":
|
||||
childLeft = x;
|
||||
childTop = y;
|
||||
childWidth = remainingWidth;
|
||||
@@ -117,21 +115,21 @@ export class DockLayout extends common.DockLayout {
|
||||
remainingHeight = Math.max(0, remainingHeight - childHeight);
|
||||
break;
|
||||
|
||||
case Dock.bottom:
|
||||
case "bottom":
|
||||
childLeft = x;
|
||||
childTop = y + remainingHeight - childHeight;
|
||||
childWidth = remainingWidth;
|
||||
remainingHeight = Math.max(0, remainingHeight - childHeight);
|
||||
break;
|
||||
|
||||
case Dock.right:
|
||||
case "right":
|
||||
childLeft = x + remainingWidth - childWidth;
|
||||
childTop = y;
|
||||
childHeight = remainingHeight;
|
||||
remainingWidth = Math.max(0, remainingWidth - childWidth);
|
||||
break;
|
||||
|
||||
case Dock.left:
|
||||
case "left":
|
||||
default:
|
||||
childLeft = x;
|
||||
childTop = y;
|
||||
@@ -143,7 +141,5 @@ export class DockLayout extends common.DockLayout {
|
||||
|
||||
View.layoutChild(this, child, childLeft, childTop, childLeft + childWidth, childTop + childHeight);
|
||||
});
|
||||
|
||||
DockLayout.restoreOriginalParams(this);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,7 @@
|
||||
import definition = require("ui/layouts/grid-layout");
|
||||
import {LayoutBase} from "ui/layouts/layout-base";
|
||||
import {View, ApplyXmlAttributes} from "ui/core/view";
|
||||
import {Bindable} from "ui/core/bindable";
|
||||
import {PropertyMetadata} from "ui/core/proxy";
|
||||
import {Property, PropertyMetadataSettings, PropertyChangeData} from "ui/core/dependency-observable";
|
||||
import {registerSpecialProperty} from "ui/builder/special-properties";
|
||||
import numberUtils = require("../../../utils/number-utils");
|
||||
import * as typesModule from "utils/types";
|
||||
|
||||
var types: typeof typesModule;
|
||||
function ensureTypes() {
|
||||
if (!types) {
|
||||
types = require("utils/types");
|
||||
}
|
||||
}
|
||||
import { GridLayout as GridLayoutDefinition, ItemSpec as ItemSpecDefinition } from "ui/layouts/grid-layout";
|
||||
import { LayoutBase, View, Bindable, Property } from "ui/layouts/layout-base";
|
||||
|
||||
export * from "ui/layouts/layout-base";
|
||||
function validateArgs(element: View): View {
|
||||
if (!element) {
|
||||
throw new Error("element cannot be null or undefinied.");
|
||||
@@ -22,49 +9,89 @@ function validateArgs(element: View): View {
|
||||
return element;
|
||||
}
|
||||
|
||||
export module GridUnitType {
|
||||
export var auto: string = "auto";
|
||||
export var pixel: string = "pixel";
|
||||
export var star: string = "star";
|
||||
declare module "ui/core/view" {
|
||||
interface View {
|
||||
row: number;
|
||||
col: number;
|
||||
rowSpan: number;
|
||||
colSpan: number;
|
||||
}
|
||||
}
|
||||
|
||||
registerSpecialProperty("row", (instance, propertyValue) => {
|
||||
GridLayout.setRow(instance, !isNaN(+propertyValue) && +propertyValue);
|
||||
});
|
||||
registerSpecialProperty("col", (instance, propertyValue) => {
|
||||
GridLayout.setColumn(instance, !isNaN(+propertyValue) && +propertyValue);
|
||||
});
|
||||
registerSpecialProperty("colSpan", (instance, propertyValue) => {
|
||||
GridLayout.setColumnSpan(instance, !isNaN(+propertyValue) && +propertyValue);
|
||||
});
|
||||
registerSpecialProperty("rowSpan", (instance, propertyValue) => {
|
||||
GridLayout.setRowSpan(instance, !isNaN(+propertyValue) && +propertyValue);
|
||||
});
|
||||
View.prototype.row = 0;
|
||||
View.prototype.col = 0;
|
||||
View.prototype.rowSpan = 1;
|
||||
View.prototype.colSpan = 1;
|
||||
|
||||
export class ItemSpec extends Bindable implements definition.ItemSpec {
|
||||
function convertUnitType(value: string): "pixel" | "star" | "auto" {
|
||||
if (value === "pixel" || value === "star" || value === "auto") {
|
||||
return <"pixel" | "star" | "auto">value;
|
||||
}
|
||||
|
||||
throw new Error(`Invalid value for unitType: ${value}`);
|
||||
}
|
||||
|
||||
function 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.");
|
||||
}
|
||||
}
|
||||
|
||||
function convertGridLength(value: string): ItemSpec {
|
||||
if (value === "auto") {
|
||||
return ItemSpec.create(1, "auto");
|
||||
}
|
||||
else if (value.indexOf("*") !== -1) {
|
||||
const starCount = parseInt(value.replace("*", "") || "1");
|
||||
return ItemSpec.create(starCount, "star");
|
||||
}
|
||||
else if (!isNaN(parseInt(value))) {
|
||||
return ItemSpec.create(parseInt(value), "pixel");
|
||||
}
|
||||
else {
|
||||
throw new Error(`Cannot parse item spec from string: ${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
function parseAndAddItemSpecs(value: string, func: (itemSpec: ItemSpec) => void): void {
|
||||
const arr = value.split(/[\s,]+/);
|
||||
for (let i = 0, length = arr.length; i < length; i++) {
|
||||
const str = arr[i].trim();
|
||||
if (str.length > 0) {
|
||||
func(convertGridLength(arr[i].trim()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ItemSpec extends Bindable implements ItemSpecDefinition {
|
||||
private _value: number;
|
||||
private _unitType: string;
|
||||
private _unitType: "pixel" | "star" | "auto";
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
if (arguments.length === 0) {
|
||||
this._value = 1;
|
||||
this._unitType = GridUnitType.star;
|
||||
this._unitType = "star";
|
||||
|
||||
}
|
||||
else if (arguments.length === 2) {
|
||||
ensureTypes();
|
||||
|
||||
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.");
|
||||
const value = arguments[0];
|
||||
const type = arguments[1];
|
||||
if (typeof value === "number" && typeof type === "string") {
|
||||
if (value < 0 || isNaN(value) || !isFinite(value)) {
|
||||
throw new Error(`Value should not be negative, NaN or Infinity: ${value}`);
|
||||
}
|
||||
this._value = arguments[0];
|
||||
this._unitType = arguments[1];
|
||||
|
||||
this._value = value;
|
||||
this._unitType = convertUnitType(type);
|
||||
}
|
||||
else {
|
||||
throw new Error("Arguments must be number and string.");
|
||||
throw new Error("First argument should be number, second argument should be string.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -74,11 +101,11 @@ export class ItemSpec extends Bindable implements definition.ItemSpec {
|
||||
this.index = -1;
|
||||
}
|
||||
|
||||
public owner: GridLayout;
|
||||
public owner: GridLayoutBase;
|
||||
public index: number;
|
||||
public _actualLength: number = 0;
|
||||
|
||||
public static create(value: number, type: string): ItemSpec {
|
||||
public static create(value: number, type: "pixel" | "star" | "auto"): ItemSpec {
|
||||
let spec = new ItemSpec();
|
||||
spec._value = value;
|
||||
spec._unitType = type;
|
||||
@@ -88,28 +115,25 @@ export class ItemSpec extends Bindable implements definition.ItemSpec {
|
||||
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 {
|
||||
get gridUnitType(): "pixel" | "star" | "auto" {
|
||||
return this._unitType;
|
||||
}
|
||||
|
||||
get isAbsolute(): boolean {
|
||||
return this._unitType === GridUnitType.pixel;
|
||||
return this._unitType === "pixel";
|
||||
}
|
||||
|
||||
get isAuto(): boolean {
|
||||
return this._unitType === GridUnitType.auto;
|
||||
return this._unitType === "auto";
|
||||
}
|
||||
|
||||
get isStar(): boolean {
|
||||
return this._unitType === GridUnitType.star;
|
||||
return this._unitType === "star";
|
||||
}
|
||||
|
||||
get value(): number {
|
||||
@@ -117,56 +141,44 @@ export class ItemSpec extends Bindable implements definition.ItemSpec {
|
||||
}
|
||||
}
|
||||
|
||||
export class GridLayout extends LayoutBase implements definition.GridLayout, ApplyXmlAttributes {
|
||||
export class GridLayoutBase extends LayoutBase implements GridLayoutDefinition {
|
||||
private _rows: Array<ItemSpec> = new Array<ItemSpec>();
|
||||
private _cols: Array<ItemSpec> = new Array<ItemSpec>();
|
||||
|
||||
public static columnProperty = new Property("Column", "GridLayout",
|
||||
new PropertyMetadata(0, PropertyMetadataSettings.None, GridLayout.onColumnPropertyChanged, numberUtils.notNegative));
|
||||
|
||||
public static columnSpanProperty = new Property("ColumnSpan", "GridLayout",
|
||||
new PropertyMetadata(1, PropertyMetadataSettings.None, GridLayout.onColumnSpanPropertyChanged, numberUtils.greaterThanZero));
|
||||
|
||||
public static rowProperty = new Property("Row", "GridLayout",
|
||||
new PropertyMetadata(0, PropertyMetadataSettings.None, GridLayout.onRowPropertyChanged, numberUtils.notNegative));
|
||||
|
||||
public static rowSpanProperty = new Property("RowSpan", "GridLayout",
|
||||
new PropertyMetadata(1, PropertyMetadataSettings.None, GridLayout.onRowSpanPropertyChanged, numberUtils.greaterThanZero));
|
||||
|
||||
public static getColumn(element: View): number {
|
||||
return validateArgs(element)._getValue(GridLayout.columnProperty);
|
||||
return validateArgs(element).col;
|
||||
}
|
||||
|
||||
public static setColumn(element: View, value: number): void {
|
||||
validateArgs(element)._setValue(GridLayout.columnProperty, value);
|
||||
validateArgs(element).col = value;
|
||||
}
|
||||
|
||||
public static getColumnSpan(element: View): number {
|
||||
return validateArgs(element)._getValue(GridLayout.columnSpanProperty);
|
||||
return validateArgs(element).colSpan;
|
||||
}
|
||||
|
||||
public static setColumnSpan(element: View, value: number): void {
|
||||
validateArgs(element)._setValue(GridLayout.columnSpanProperty, value);
|
||||
validateArgs(element).colSpan = value;
|
||||
}
|
||||
|
||||
public static getRow(element: View): number {
|
||||
return validateArgs(element)._getValue(GridLayout.rowProperty);
|
||||
return validateArgs(element).row;
|
||||
}
|
||||
|
||||
public static setRow(element: View, value: number): void {
|
||||
validateArgs(element)._setValue(GridLayout.rowProperty, value);
|
||||
validateArgs(element).row = value;
|
||||
}
|
||||
|
||||
public static getRowSpan(element: View): number {
|
||||
return validateArgs(element)._getValue(GridLayout.rowSpanProperty);
|
||||
return validateArgs(element).rowSpan;
|
||||
}
|
||||
|
||||
public static setRowSpan(element: View, value: number): void {
|
||||
validateArgs(element)._setValue(GridLayout.rowSpanProperty, value);
|
||||
validateArgs(element).rowSpan = value;
|
||||
}
|
||||
|
||||
public addRow(itemSpec: ItemSpec) {
|
||||
GridLayout.validateItemSpec(itemSpec);
|
||||
validateItemSpec(itemSpec);
|
||||
itemSpec.owner = this;
|
||||
this._rows.push(itemSpec);
|
||||
this._onRowAdded(itemSpec);
|
||||
@@ -174,7 +186,7 @@ export class GridLayout extends LayoutBase implements definition.GridLayout, App
|
||||
}
|
||||
|
||||
public addColumn(itemSpec: ItemSpec) {
|
||||
GridLayout.validateItemSpec(itemSpec);
|
||||
validateItemSpec(itemSpec);
|
||||
itemSpec.owner = this;
|
||||
this._cols.push(itemSpec);
|
||||
this._onColumnAdded(itemSpec);
|
||||
@@ -233,19 +245,19 @@ export class GridLayout extends LayoutBase implements definition.GridLayout, App
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
protected onRowChanged(element: View, oldValue: number, newValue: number) {
|
||||
public onRowChanged(element: View, oldValue: number, newValue: number) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
protected onRowSpanChanged(element: View, oldValue: number, newValue: number) {
|
||||
public onRowSpanChanged(element: View, oldValue: number, newValue: number) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
protected onColumnChanged(element: View, oldValue: number, newValue: number) {
|
||||
public onColumnChanged(element: View, oldValue: number, newValue: number) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
protected onColumnSpanChanged(element: View, oldValue: number, newValue: number) {
|
||||
public onColumnSpanChanged(element: View, oldValue: number, newValue: number) {
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
@@ -280,7 +292,7 @@ export class GridLayout extends LayoutBase implements definition.GridLayout, App
|
||||
protected get rowsInternal(): Array<ItemSpec> {
|
||||
return this._rows;
|
||||
}
|
||||
|
||||
|
||||
protected invalidate(): void {
|
||||
this.requestLayout();
|
||||
}
|
||||
@@ -298,98 +310,61 @@ export class GridLayout extends LayoutBase implements definition.GridLayout, App
|
||||
return super._applyXmlAttribute(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
private static parseItemSpecs(value: string): Array<ItemSpec> {
|
||||
var result = new Array<ItemSpec>();
|
||||
var arr = value.split(/[\s,]+/);
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
let str = arr[i].trim();
|
||||
if (str.length > 0) {
|
||||
result.push(GridLayout.convertGridLength(arr[i].trim()));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static convertGridLength(value: string): ItemSpec {
|
||||
if (value === "auto") {
|
||||
return ItemSpec.create(1, GridUnitType.auto);
|
||||
}
|
||||
else if (value.indexOf("*") !== -1) {
|
||||
var starCount = parseInt(value.replace("*", "") || "1");
|
||||
return ItemSpec.create(starCount, GridUnitType.star);
|
||||
}
|
||||
else if (!isNaN(parseInt(value))) {
|
||||
return ItemSpec.create(parseInt(value), GridUnitType.pixel);
|
||||
}
|
||||
else {
|
||||
throw new Error("Cannot parse item spec from string: " + value);
|
||||
}
|
||||
}
|
||||
|
||||
private static onRowPropertyChanged(data: 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: 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: 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: 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 {
|
||||
if (object instanceof View) {
|
||||
return object;
|
||||
}
|
||||
|
||||
throw new Error("Element is not View or its descendant.");
|
||||
}
|
||||
|
||||
private _setColumns(value: string) {
|
||||
this.removeColumns();
|
||||
let columns = GridLayout.parseItemSpecs(value);
|
||||
for (let i = 0, count = columns.length; i < count; i++) {
|
||||
this.addColumn(columns[i]);
|
||||
}
|
||||
parseAndAddItemSpecs(value, (spec: ItemSpec) => this.addColumn(spec));
|
||||
}
|
||||
|
||||
private _setRows(value: string) {
|
||||
this.removeRows();
|
||||
let rows = GridLayout.parseItemSpecs(value);
|
||||
for (let i = 0, count = rows.length; i < count; i++) {
|
||||
this.addRow(rows[i]);
|
||||
}
|
||||
parseAndAddItemSpecs(value, (spec: ItemSpec) => this.addRow(spec));
|
||||
}
|
||||
}
|
||||
|
||||
export const columnProperty = new Property<View, number>({
|
||||
name: "col", defaultValue: 0,
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
const grid = target.parent;
|
||||
if (grid instanceof GridLayoutBase) {
|
||||
grid.onColumnChanged(target, oldValue, newValue);
|
||||
}
|
||||
},
|
||||
valueConverter: (v) => Math.max(0, parseInt(v))
|
||||
});
|
||||
columnProperty.register(GridLayoutBase);
|
||||
|
||||
export const columnSpanProperty = new Property<View, number>({
|
||||
name: "colSpan", defaultValue: 1,
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
const grid = target.parent;
|
||||
if (grid instanceof GridLayoutBase) {
|
||||
grid.onColumnSpanChanged(target, oldValue, newValue);
|
||||
}
|
||||
},
|
||||
valueConverter: (v) => Math.max(1, parseInt(v))
|
||||
});
|
||||
columnSpanProperty.register(GridLayoutBase);
|
||||
|
||||
export const rowProperty = new Property<View, number>({
|
||||
name: "row", defaultValue: 0,
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
const grid = target.parent;
|
||||
if (grid instanceof GridLayoutBase) {
|
||||
grid.onRowChanged(target, oldValue, newValue);
|
||||
}
|
||||
},
|
||||
valueConverter: (v) => Math.max(0, parseInt(v))
|
||||
});
|
||||
rowProperty.register(GridLayoutBase);
|
||||
|
||||
export const rowSpanProperty = new Property<View, number>({
|
||||
name: "rowSpan", defaultValue: 1,
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
const grid = target.parent;
|
||||
if (grid instanceof GridLayoutBase) {
|
||||
grid.onRowSpanChanged(target, oldValue, newValue);
|
||||
}
|
||||
},
|
||||
valueConverter: (v) => Math.max(1, parseInt(v))
|
||||
});
|
||||
rowSpanProperty.register(GridLayoutBase);
|
||||
@@ -1,73 +1,100 @@
|
||||
import utils = require("utils/utils");
|
||||
import common = require("./grid-layout-common");
|
||||
import {View} from "ui/core/view";
|
||||
import {PropertyMetadata} from "ui/core/proxy";
|
||||
import {PropertyChangeData} from "ui/core/dependency-observable";
|
||||
import {
|
||||
GridLayoutBase, ItemSpec as ItemSpecBase, View, layout,
|
||||
rowProperty, columnProperty, rowSpanProperty, columnSpanProperty
|
||||
} from "./grid-layout-common";
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
export * from "./grid-layout-common";
|
||||
|
||||
function setNativeProperty(data: PropertyChangeData, setter: (lp: org.nativescript.widgets.CommonLayoutParams) => void) {
|
||||
let view = data.object;
|
||||
if (view instanceof View) {
|
||||
let nativeView: android.view.View = view._nativeView;
|
||||
var lp = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams();
|
||||
if (lp instanceof org.nativescript.widgets.CommonLayoutParams) {
|
||||
setter(lp);
|
||||
nativeView.setLayoutParams(lp);
|
||||
}
|
||||
function setNativeProperty(view: View, setter: (lp: org.nativescript.widgets.CommonLayoutParams) => void) {
|
||||
let nativeView: android.view.View = view._nativeView;
|
||||
const lp = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams();
|
||||
if (lp instanceof org.nativescript.widgets.CommonLayoutParams) {
|
||||
setter(lp);
|
||||
nativeView.setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
|
||||
function setNativeRowProperty(data: PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.row = data.newValue; });
|
||||
// define native getter and setter for rowProperty.
|
||||
let rowDescriptor: TypedPropertyDescriptor<number> = {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
get: () => 0,
|
||||
set: function (this: View, value: number) {
|
||||
setNativeProperty(this, (lp) => lp.row = value);
|
||||
}
|
||||
}
|
||||
|
||||
function setNativeRowSpanProperty(data: PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.rowSpan = data.newValue; });
|
||||
// define native getter and setter for columnProperty.
|
||||
let colDescriptor: TypedPropertyDescriptor<number> = {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
get: () => 0,
|
||||
set: function (this: View, value: number) {
|
||||
setNativeProperty(this, (lp) => lp.column = value);
|
||||
}
|
||||
}
|
||||
|
||||
function setNativeColumnProperty(data: PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.column = data.newValue; });
|
||||
// define native getter and setter for rowSpanProperty.
|
||||
let rowSpanDescriptor: TypedPropertyDescriptor<number> = {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
get: () => 1,
|
||||
set: function (this: View, value: number) {
|
||||
setNativeProperty(this, (lp) => lp.rowSpan = value);
|
||||
}
|
||||
}
|
||||
|
||||
function setNativeColumnSpanProperty(data: PropertyChangeData) {
|
||||
setNativeProperty(data, (lp) => { lp.columnSpan = data.newValue; });
|
||||
// define native getter and setter for columnSpanProperty.
|
||||
let colSpanDescriptor: TypedPropertyDescriptor<number> = {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
get: () => 1,
|
||||
set: function (this: View, value: number) {
|
||||
setNativeProperty(this, (lp) => lp.columnSpan = value);
|
||||
}
|
||||
}
|
||||
|
||||
(<PropertyMetadata>common.GridLayout.rowProperty.metadata).onSetNativeValue = setNativeRowProperty;
|
||||
(<PropertyMetadata>common.GridLayout.rowSpanProperty.metadata).onSetNativeValue = setNativeRowSpanProperty;
|
||||
(<PropertyMetadata>common.GridLayout.columnProperty.metadata).onSetNativeValue = setNativeColumnProperty;
|
||||
(<PropertyMetadata>common.GridLayout.columnSpanProperty.metadata).onSetNativeValue = setNativeColumnSpanProperty;
|
||||
// register native properties on View type.
|
||||
Object.defineProperties(View, {
|
||||
[rowProperty.native]: rowDescriptor,
|
||||
[columnProperty.native]: colDescriptor,
|
||||
[rowSpanProperty.native]: rowSpanDescriptor,
|
||||
[columnSpanProperty.native]: colSpanDescriptor
|
||||
});
|
||||
|
||||
function createNativeSpec(itemSpec: ItemSpec): org.nativescript.widgets.ItemSpec {
|
||||
switch (itemSpec.gridUnitType) {
|
||||
case common.GridUnitType.auto:
|
||||
case "auto":
|
||||
return new org.nativescript.widgets.ItemSpec(itemSpec.value, org.nativescript.widgets.GridUnitType.auto);
|
||||
|
||||
case common.GridUnitType.star:
|
||||
case "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);
|
||||
case "pixel":
|
||||
return new org.nativescript.widgets.ItemSpec(itemSpec.value * layout.getDisplayDensity(), org.nativescript.widgets.GridUnitType.pixel);
|
||||
|
||||
default:
|
||||
throw new Error("Invalid gridUnitType: " + itemSpec.gridUnitType);
|
||||
}
|
||||
}
|
||||
|
||||
export class ItemSpec extends common.ItemSpec {
|
||||
export class ItemSpec extends ItemSpecBase {
|
||||
nativeSpec: org.nativescript.widgets.ItemSpec;
|
||||
|
||||
public get actualLength(): number {
|
||||
if (this.nativeSpec) {
|
||||
return Math.round(this.nativeSpec.getActualLength() / utils.layout.getDisplayDensity());
|
||||
return Math.round(this.nativeSpec.getActualLength() / layout.getDisplayDensity());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export class GridLayout extends common.GridLayout {
|
||||
export class GridLayout extends GridLayoutBase {
|
||||
|
||||
private _layout: org.nativescript.widgets.GridLayout;
|
||||
|
||||
@@ -81,7 +108,7 @@ export class GridLayout extends common.GridLayout {
|
||||
|
||||
public _createUI() {
|
||||
this._layout = new org.nativescript.widgets.GridLayout(this._context);
|
||||
|
||||
|
||||
// Update native GridLayout
|
||||
this.getRows().forEach((itemSpec: ItemSpec, index, rows) => { this._onRowAdded(itemSpec); }, this);
|
||||
this.getColumns().forEach((itemSpec: ItemSpec, index, rows) => { this._onColumnAdded(itemSpec); }, this);
|
||||
@@ -89,7 +116,7 @@ export class GridLayout extends common.GridLayout {
|
||||
|
||||
public _onRowAdded(itemSpec: ItemSpec) {
|
||||
if (this._layout) {
|
||||
var nativeSpec = createNativeSpec(itemSpec);
|
||||
const nativeSpec = createNativeSpec(itemSpec);
|
||||
itemSpec.nativeSpec = nativeSpec;
|
||||
this._layout.addRow(nativeSpec);
|
||||
}
|
||||
@@ -97,7 +124,7 @@ export class GridLayout extends common.GridLayout {
|
||||
|
||||
public _onColumnAdded(itemSpec: ItemSpec) {
|
||||
if (this._layout) {
|
||||
var nativeSpec = createNativeSpec(itemSpec);
|
||||
const nativeSpec = createNativeSpec(itemSpec);
|
||||
itemSpec.nativeSpec = nativeSpec;
|
||||
this._layout.addColumn(nativeSpec);
|
||||
}
|
||||
@@ -120,4 +147,4 @@ export class GridLayout extends common.GridLayout {
|
||||
protected invalidate(): void {
|
||||
// No need to request layout for android because it will be done in the native call.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,5 @@
|
||||
declare module "ui/layouts/grid-layout" {
|
||||
import {LayoutBase} from "ui/layouts/layout-base";
|
||||
import {View} from "ui/core/view";
|
||||
import {Property} from "ui/core/dependency-observable";
|
||||
|
||||
/**
|
||||
* GridUnitType enum is used to indicate what kind of value the ItemSpec is holding.
|
||||
*/
|
||||
module GridUnitType {
|
||||
/**
|
||||
* The value indicates that content should be calculated without constraints.
|
||||
*/
|
||||
export var auto: string;
|
||||
/**
|
||||
* The value is expressed as a pixel.
|
||||
*/
|
||||
export var pixel: string;
|
||||
/**
|
||||
* The value is expressed as a weighted proportion of available space.
|
||||
*/
|
||||
export var star: string;
|
||||
}
|
||||
import { LayoutBase, Property, View } from "ui/layouts/layout-base";
|
||||
|
||||
/**
|
||||
* Defines row/column specific properties that apply to GridLayout elements.
|
||||
@@ -27,10 +7,7 @@
|
||||
export class ItemSpec {
|
||||
|
||||
constructor();
|
||||
constructor(value: number, type: string);
|
||||
constructor(value: number, type: "pixel");
|
||||
constructor(value: number, type: "star");
|
||||
constructor(value: number, type: "auto");
|
||||
constructor(value: number, type: "pixel" | "star" | "auto");
|
||||
|
||||
/**
|
||||
* Gets the actual length of an ItemSpec.
|
||||
@@ -40,7 +17,7 @@
|
||||
/**
|
||||
* Returns unit type of this ItemSpec instance.
|
||||
*/
|
||||
gridUnitType: string;
|
||||
gridUnitType: "pixel" | "star" | "auto";
|
||||
|
||||
/**
|
||||
* Returns true if this ItemSpec instance holds
|
||||
@@ -71,31 +48,6 @@
|
||||
*/
|
||||
export class GridLayout extends LayoutBase {
|
||||
|
||||
///**
|
||||
// * Initializes a new instance of GridLayout.
|
||||
// * @param options Options to configure this GridLayout instance.
|
||||
// */
|
||||
//constructor(options?: Options);
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the column property.
|
||||
*/
|
||||
public static columnProperty: Property;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the columnSpan property.
|
||||
*/
|
||||
public static columnSpanProperty: Property;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the row property.
|
||||
*/
|
||||
public static rowProperty: Property;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the rowSpan property.
|
||||
*/
|
||||
public static rowSpanProperty: Property;
|
||||
/**
|
||||
* Gets the value of the Column attached property from a given View.
|
||||
*/
|
||||
@@ -183,4 +135,24 @@
|
||||
public _onColumnRemoved(itemSpec: ItemSpec, index: number): void;
|
||||
//@endprivate
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the column property.
|
||||
*/
|
||||
export const columnProperty: Property<GridLayout, number>;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the columnSpan property.
|
||||
*/
|
||||
export const columnSpanProperty: Property<GridLayout, number>;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the row property.
|
||||
*/
|
||||
export const rowProperty: Property<GridLayout, number>;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the rowSpan property.
|
||||
*/
|
||||
export const rowSpanProperty: Property<GridLayout, number>;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import utils = require("utils/utils");
|
||||
import common = require("./grid-layout-common");
|
||||
import {View} from "ui/core/view";
|
||||
import {HorizontalAlignment, VerticalAlignment} from "ui/enums";
|
||||
import {
|
||||
GridLayoutBase, ItemSpec, View, layout,
|
||||
rowProperty, columnProperty, rowSpanProperty, columnSpanProperty
|
||||
} from "./grid-layout-common";
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
export * from "./grid-layout-common";
|
||||
|
||||
export class GridLayout extends common.GridLayout {
|
||||
export class GridLayout extends GridLayoutBase {
|
||||
private helper: MeasureHelper;
|
||||
private columnOffsets = new Array<number>();
|
||||
private rowOffsets = new Array<number>();
|
||||
@@ -16,20 +16,20 @@ export class GridLayout extends common.GridLayout {
|
||||
this.helper = new MeasureHelper(this);
|
||||
}
|
||||
|
||||
public _onRowAdded(itemSpec: common.ItemSpec) {
|
||||
public _onRowAdded(itemSpec: ItemSpec) {
|
||||
this.helper.rows.push(new ItemGroup(itemSpec));
|
||||
}
|
||||
|
||||
public _onColumnAdded(itemSpec: common.ItemSpec) {
|
||||
public _onColumnAdded(itemSpec: ItemSpec) {
|
||||
this.helper.columns.push(new ItemGroup(itemSpec));
|
||||
}
|
||||
|
||||
public _onRowRemoved(itemSpec: common.ItemSpec, index: number) {
|
||||
public _onRowRemoved(itemSpec: ItemSpec, index: number) {
|
||||
this.helper.rows[index].children.length = 0;
|
||||
this.helper.rows.splice(index, 1);
|
||||
}
|
||||
|
||||
public _onColumnRemoved(itemSpec: common.ItemSpec, index: number) {
|
||||
public _onColumnRemoved(itemSpec: ItemSpec, index: number) {
|
||||
this.helper.columns[index].children.length = 0;
|
||||
this.helper.columns.splice(index, 1);
|
||||
}
|
||||
@@ -58,11 +58,11 @@ export class GridLayout extends common.GridLayout {
|
||||
return Math.max(1, Math.min(GridLayout.getRowSpan(view), this.rowsInternal.length - rowIndex));
|
||||
}
|
||||
|
||||
private getColumnSpec(view: View): common.ItemSpec {
|
||||
private getColumnSpec(view: View): ItemSpec {
|
||||
return this.columnsInternal[this.getColumnIndex(view)] || this.helper.singleColumn;
|
||||
}
|
||||
|
||||
private getRowSpec(view: View): common.ItemSpec {
|
||||
private getRowSpec(view: View): ItemSpec {
|
||||
return this.rowsInternal[this.getRowIndex(view)] || this.helper.singleRow;
|
||||
}
|
||||
|
||||
@@ -101,30 +101,29 @@ export class GridLayout extends common.GridLayout {
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
GridLayout.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
let measureWidth = 0;
|
||||
let measureHeight = 0;
|
||||
|
||||
let width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
let widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
let height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
let heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
let density = utils.layout.getDisplayDensity();
|
||||
let verticalPadding = (this.borderTopWidth + this.paddingTop + this.paddingBottom + this.borderBottomWidth) * density;
|
||||
let horizontalPadding = (this.borderLeftWidth + this.paddingLeft + this.paddingRight + this.borderRightWidth) * density;
|
||||
const style = this.style;
|
||||
const horizontalPaddingsAndMargins = style.effectivePaddingLeft + style.effectivePaddingRight + style.effectiveBorderLeftWidth + style.effectiveBorderRightWidth;
|
||||
const verticalPaddingsAndMargins = style.effectivePaddingTop + style.effectivePaddingBottom + style.effectiveBorderTopWidth + style.effectiveBorderBottomWidth;
|
||||
|
||||
let infinityWidth = widthMode === utils.layout.UNSPECIFIED;
|
||||
let infinityHeight = heightMode === utils.layout.UNSPECIFIED;
|
||||
let infinityWidth = widthMode === layout.UNSPECIFIED;
|
||||
let infinityHeight = heightMode === layout.UNSPECIFIED;
|
||||
|
||||
this.helper.width = Math.max(0, width - horizontalPadding);
|
||||
this.helper.height = Math.max(0, height - verticalPadding);
|
||||
this.helper.width = Math.max(0, width - horizontalPaddingsAndMargins);
|
||||
this.helper.height = Math.max(0, height - verticalPaddingsAndMargins);
|
||||
|
||||
this.helper.stretchedHorizontally = widthMode === utils.layout.EXACTLY || (this.horizontalAlignment === HorizontalAlignment.stretch && !infinityWidth);
|
||||
this.helper.stretchedVertically = heightMode === utils.layout.EXACTLY || (this.verticalAlignment === VerticalAlignment.stretch && !infinityHeight);
|
||||
this.helper.stretchedHorizontally = widthMode === layout.EXACTLY || (this.horizontalAlignment === "stretch" && !infinityWidth);
|
||||
this.helper.stretchedVertically = heightMode === layout.EXACTLY || (this.verticalAlignment === "stretch" && !infinityHeight);
|
||||
|
||||
this.helper.setInfinityWidth(infinityWidth);
|
||||
this.helper.setInfinityHeight(infinityHeight);
|
||||
@@ -141,15 +140,15 @@ export class GridLayout extends common.GridLayout {
|
||||
this.helper.measure();
|
||||
|
||||
// Add in our padding
|
||||
measureWidth = this.helper.measuredWidth + horizontalPadding;
|
||||
measureHeight = this.helper.measuredHeight + verticalPadding;
|
||||
measureWidth = this.helper.measuredWidth + horizontalPaddingsAndMargins;
|
||||
measureHeight = this.helper.measuredHeight + verticalPaddingsAndMargins;
|
||||
|
||||
// Check against our minimum sizes
|
||||
measureWidth = Math.max(measureWidth, this.minWidth * density);
|
||||
measureHeight = Math.max(measureHeight, this.minHeight * density);
|
||||
measureWidth = Math.max(measureWidth, style.effectiveMinWidth);
|
||||
measureHeight = Math.max(measureHeight, style.effectiveMinHeight);
|
||||
|
||||
let widthSizeAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
let heightSizeAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
const widthSizeAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
const heightSizeAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthSizeAndState, heightSizeAndState);
|
||||
}
|
||||
@@ -157,10 +156,10 @@ export class GridLayout extends common.GridLayout {
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
super.onLayout(left, top, right, bottom);
|
||||
|
||||
let density = utils.layout.getDisplayDensity();
|
||||
const style = this.style;
|
||||
|
||||
let paddingLeft = (this.borderLeftWidth + this.paddingLeft) * density;
|
||||
let paddingTop = (this.borderTopWidth + this.paddingTop) * density;
|
||||
let paddingLeft = style.effectiveBorderLeftWidth + style.effectivePaddingLeft;
|
||||
let paddingTop = style.effectiveBorderTopWidth + style.effectivePaddingTop;
|
||||
|
||||
this.columnOffsets.length = 0;
|
||||
this.rowOffsets.length = 0;
|
||||
@@ -211,13 +210,11 @@ export class GridLayout extends common.GridLayout {
|
||||
let childRight = this.columnOffsets[measureSpec.getColumnIndex() + measureSpec.getColumnSpan()];
|
||||
let childTop = this.rowOffsets[measureSpec.getRowIndex()];
|
||||
let childBottom = this.rowOffsets[measureSpec.getRowIndex() + measureSpec.getRowSpan()];
|
||||
|
||||
|
||||
// No need to include margins in the width, height
|
||||
View.layoutChild(this, measureSpec.child, childLeft, childTop, childRight, childBottom);
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout.restoreOriginalParams(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,8 +234,8 @@ class MeasureSpecs {
|
||||
public measured = false;
|
||||
|
||||
public child: View;
|
||||
private column: common.ItemSpec;
|
||||
private row: common.ItemSpec
|
||||
private column: ItemSpec;
|
||||
private row: ItemSpec
|
||||
private columnIndex: number = 0;
|
||||
private rowIndex: number = 0;
|
||||
|
||||
@@ -288,19 +285,19 @@ class MeasureSpecs {
|
||||
this.columnIndex = value;
|
||||
}
|
||||
|
||||
public getRow(): common.ItemSpec {
|
||||
public getRow(): ItemSpec {
|
||||
return this.row;
|
||||
}
|
||||
|
||||
public getColumn(): common.ItemSpec {
|
||||
public getColumn(): ItemSpec {
|
||||
return this.column;
|
||||
}
|
||||
|
||||
public setRow(value: common.ItemSpec): void {
|
||||
public setRow(value: ItemSpec): void {
|
||||
this.row = value;
|
||||
}
|
||||
|
||||
public setColumn(value: common.ItemSpec): void {
|
||||
public setColumn(value: ItemSpec): void {
|
||||
this.column = value;
|
||||
}
|
||||
}
|
||||
@@ -308,14 +305,14 @@ class MeasureSpecs {
|
||||
class ItemGroup {
|
||||
public length = 0;
|
||||
public measuredCount = 0;
|
||||
public rowOrColumn: common.ItemSpec;
|
||||
public rowOrColumn: ItemSpec;
|
||||
public children: Array<MeasureSpecs> = new Array<MeasureSpecs>();
|
||||
|
||||
public measureToFix = 0;
|
||||
public currentMeasureToFixCount = 0;
|
||||
private infinityLength = false;
|
||||
|
||||
constructor(spec: common.ItemSpec) {
|
||||
constructor(spec: ItemSpec) {
|
||||
this.rowOrColumn = spec;
|
||||
}
|
||||
|
||||
@@ -351,11 +348,11 @@ class ItemGroup {
|
||||
}
|
||||
|
||||
class MeasureHelper {
|
||||
singleRow: common.ItemSpec;
|
||||
singleColumn: common.ItemSpec;
|
||||
singleRow: ItemSpec;
|
||||
singleColumn: ItemSpec;
|
||||
grid: GridLayout;
|
||||
|
||||
infinity: number = utils.layout.makeMeasureSpec(0, utils.layout.UNSPECIFIED);
|
||||
infinity: number = layout.makeMeasureSpec(0, layout.UNSPECIFIED);
|
||||
rows: Array<ItemGroup> = new Array<ItemGroup>();
|
||||
columns: Array<ItemGroup> = new Array<ItemGroup>();
|
||||
|
||||
@@ -384,8 +381,8 @@ class MeasureHelper {
|
||||
|
||||
constructor(grid: GridLayout) {
|
||||
this.grid = grid;
|
||||
this.singleRow = new common.ItemSpec();
|
||||
this.singleColumn = new common.ItemSpec();
|
||||
this.singleRow = new ItemSpec();
|
||||
this.singleColumn = new ItemSpec();
|
||||
this.singleRowGroup = new ItemGroup(this.singleRow);
|
||||
this.singleColumnGroup = new ItemGroup(this.singleColumn);
|
||||
}
|
||||
@@ -478,7 +475,7 @@ class MeasureHelper {
|
||||
}
|
||||
|
||||
private static initList(list: Array<ItemGroup>): void {
|
||||
let density = utils.layout.getDisplayDensity();
|
||||
let density = layout.getDisplayDensity();
|
||||
for (let i = 0, size = list.length; i < size; i++) {
|
||||
let item: ItemGroup = list[i];
|
||||
item.init(density);
|
||||
@@ -667,7 +664,7 @@ class MeasureHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
public measure(): void {
|
||||
public measure(): void {
|
||||
// Measure auto & pixel columns and rows (no spans).
|
||||
let size = this.columns.length;
|
||||
for (let i = 0; i < size; i++) {
|
||||
@@ -763,8 +760,8 @@ class MeasureHelper {
|
||||
}
|
||||
|
||||
private measureChild(measureSpec: MeasureSpecs, isFakeMeasure: boolean): void {
|
||||
let widthMeasureSpec = (measureSpec.autoColumnsCount > 0) ? this.infinity : utils.layout.makeMeasureSpec(measureSpec.pixelWidth, utils.layout.EXACTLY);
|
||||
let heightMeasureSpec = (isFakeMeasure || measureSpec.autoRowsCount > 0) ? this.infinity : utils.layout.makeMeasureSpec(measureSpec.pixelHeight, utils.layout.EXACTLY);
|
||||
let widthMeasureSpec = (measureSpec.autoColumnsCount > 0) ? this.infinity : layout.makeMeasureSpec(measureSpec.pixelWidth, layout.EXACTLY);
|
||||
let heightMeasureSpec = (isFakeMeasure || measureSpec.autoRowsCount > 0) ? this.infinity : layout.makeMeasureSpec(measureSpec.pixelHeight, layout.EXACTLY);
|
||||
|
||||
let childSize = View.measureChild(null, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
|
||||
let childMeasuredWidth: number = childSize.measuredWidth;
|
||||
@@ -828,8 +825,8 @@ class MeasureHelper {
|
||||
measureWidth += columnGroup.length;
|
||||
}
|
||||
|
||||
let widthMeasureSpec = utils.layout.makeMeasureSpec(measureWidth, this.stretchedHorizontally ? utils.layout.EXACTLY : utils.layout.AT_MOST);
|
||||
let heightMeasureSpec = (measureSpec.autoRowsCount > 0) ? this.infinity : utils.layout.makeMeasureSpec(measureSpec.pixelHeight, utils.layout.EXACTLY);
|
||||
let widthMeasureSpec = layout.makeMeasureSpec(measureWidth, this.stretchedHorizontally ? layout.EXACTLY : layout.AT_MOST);
|
||||
let heightMeasureSpec = (measureSpec.autoRowsCount > 0) ? this.infinity : layout.makeMeasureSpec(measureSpec.pixelHeight, layout.EXACTLY);
|
||||
|
||||
let childSize = View.measureChild(null, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
|
||||
let childMeasuredWidth = childSize.measuredWidth;
|
||||
@@ -872,8 +869,8 @@ class MeasureHelper {
|
||||
measureHeight += rowGroup.length;
|
||||
}
|
||||
|
||||
let widthMeasureSpec = (measureSpec.autoColumnsCount > 0) ? this.infinity : utils.layout.makeMeasureSpec(measureSpec.pixelWidth, utils.layout.EXACTLY);
|
||||
let heightMeasureSpec = utils.layout.makeMeasureSpec(measureHeight, this.stretchedVertically ? utils.layout.EXACTLY : utils.layout.AT_MOST);
|
||||
let widthMeasureSpec = (measureSpec.autoColumnsCount > 0) ? this.infinity : layout.makeMeasureSpec(measureSpec.pixelWidth, layout.EXACTLY);
|
||||
let heightMeasureSpec = layout.makeMeasureSpec(measureHeight, this.stretchedVertically ? layout.EXACTLY : layout.AT_MOST);
|
||||
|
||||
let childSize = View.measureChild(null, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
|
||||
let childMeasuredWidth = childSize.measuredWidth;
|
||||
@@ -926,11 +923,11 @@ class MeasureHelper {
|
||||
}
|
||||
|
||||
// if (have stars) & (not stretch) - at most
|
||||
let widthMeasureSpec = utils.layout.makeMeasureSpec(measureWidth,
|
||||
(measureSpec.starColumnsCount > 0 && !this.stretchedHorizontally) ? utils.layout.AT_MOST : utils.layout.EXACTLY);
|
||||
let widthMeasureSpec = layout.makeMeasureSpec(measureWidth,
|
||||
(measureSpec.starColumnsCount > 0 && !this.stretchedHorizontally) ? layout.AT_MOST : layout.EXACTLY);
|
||||
|
||||
let heightMeasureSpec = utils.layout.makeMeasureSpec(measureHeight,
|
||||
(measureSpec.starRowsCount > 0 && !this.stretchedVertically) ? utils.layout.AT_MOST : utils.layout.EXACTLY);
|
||||
let heightMeasureSpec = layout.makeMeasureSpec(measureHeight,
|
||||
(measureSpec.starRowsCount > 0 && !this.stretchedVertically) ? layout.AT_MOST : layout.EXACTLY);
|
||||
|
||||
let childSize = View.measureChild(null, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
|
||||
let childMeasuredWidth = childSize.measuredWidth;
|
||||
@@ -978,4 +975,4 @@ class MeasureHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
tns-core-modules/ui/layouts/layout-base.d.ts
vendored
14
tns-core-modules/ui/layouts/layout-base.d.ts
vendored
@@ -64,20 +64,6 @@
|
||||
*/
|
||||
eachLayoutChild(callback: (child: View, isLast: boolean) => void): void;
|
||||
|
||||
/**
|
||||
* Iterates over children and changes their width and height to one calculated from percentage values.
|
||||
*
|
||||
* @param widthMeasureSpec Width MeasureSpec of the parent layout.
|
||||
* @param heightMeasureSpec Height MeasureSpec of the parent layout.
|
||||
*/
|
||||
protected static adjustChildrenLayoutParams(layoutBase: LayoutBase, widthMeasureSpec: number, heightMeasureSpec: number): void;
|
||||
|
||||
/**
|
||||
* Iterates over children and restores their original dimensions that were changed for
|
||||
* percentage values.
|
||||
*/
|
||||
protected static restoreOriginalParams(layoutBase: LayoutBase): void;
|
||||
|
||||
// /**
|
||||
// * Gets or sets padding style property.
|
||||
// */
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
import definition = require("ui/layouts/stack-layout");
|
||||
import platform = require("platform");
|
||||
import {LayoutBase} from "ui/layouts/layout-base";
|
||||
import {Orientation} from "ui/enums";
|
||||
import {PropertyMetadata} from "ui/core/proxy";
|
||||
import {Property, PropertyMetadataSettings} from "ui/core/dependency-observable";
|
||||
import { StackLayout as StackLayoutDefinition } from "ui/layouts/stack-layout";
|
||||
import { LayoutBase, Property, isIOS } from "ui/layouts/layout-base";
|
||||
|
||||
// on Android we explicitly set propertySettings to None because android will invalidate its layout (skip unnecessary native call).
|
||||
var AffectsLayout = platform.device.os === platform.platformNames.android ? PropertyMetadataSettings.None : PropertyMetadataSettings.AffectsLayout;
|
||||
export * from "ui/layouts/layout-base";
|
||||
|
||||
function validateOrientation(value: any): boolean {
|
||||
return value === Orientation.vertical || value === Orientation.horizontal;
|
||||
export class StackLayoutBase extends LayoutBase implements StackLayoutDefinition {
|
||||
public orientation: "horizontal" | "vertical";
|
||||
}
|
||||
|
||||
export class StackLayout extends LayoutBase implements definition.StackLayout {
|
||||
public static orientationProperty = new Property("orientation", "StackLayout", new PropertyMetadata(Orientation.vertical, AffectsLayout, undefined, validateOrientation));
|
||||
export const orientationProperty = new Property<StackLayoutBase, "horizontal" | "vertical">({
|
||||
name: "orientation", defaultValue: "vertical", affectsLayout: isIOS,
|
||||
valueConverter: (v) => {
|
||||
if (v === "horizontal" || v === "vertical") {
|
||||
return <"horizontal" | "vertical">v;
|
||||
}
|
||||
|
||||
get orientation(): string {
|
||||
return this._getValue(StackLayout.orientationProperty);
|
||||
throw new Error(`Invalid orientation value: ${v}`);
|
||||
}
|
||||
set orientation(value: string) {
|
||||
this._setValue(StackLayout.orientationProperty, value);
|
||||
}
|
||||
}
|
||||
});
|
||||
orientationProperty.register(StackLayoutBase);
|
||||
@@ -1,19 +1,8 @@
|
||||
import common = require("./stack-layout-common");
|
||||
import {Orientation} from "ui/enums";
|
||||
import {PropertyMetadata} from "ui/core/proxy";
|
||||
import {PropertyChangeData} from "ui/core/dependency-observable";
|
||||
import { StackLayoutBase, orientationProperty } from "./stack-layout-common";
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
export * from "./stack-layout-common";
|
||||
|
||||
function setNativeOrientationProperty(data: PropertyChangeData): void {
|
||||
var stackLayout = <StackLayout>data.object;
|
||||
var nativeView = stackLayout._nativeView;
|
||||
nativeView.setOrientation(data.newValue === Orientation.vertical ? org.nativescript.widgets.Orientation.vertical : org.nativescript.widgets.Orientation.horizontal);
|
||||
}
|
||||
|
||||
(<PropertyMetadata>common.StackLayout.orientationProperty.metadata).onSetNativeValue = setNativeOrientationProperty;
|
||||
|
||||
export class StackLayout extends common.StackLayout {
|
||||
export class StackLayout extends StackLayoutBase {
|
||||
private _layout: org.nativescript.widgets.StackLayout;
|
||||
|
||||
get android(): org.nativescript.widgets.StackLayout {
|
||||
@@ -27,4 +16,11 @@ export class StackLayout extends common.StackLayout {
|
||||
public _createUI() {
|
||||
this._layout = new org.nativescript.widgets.StackLayout(this._context);
|
||||
}
|
||||
|
||||
get [orientationProperty.native](): "horizontal" | "vertical" {
|
||||
return "vertical";
|
||||
}
|
||||
set [orientationProperty.native](value: "horizontal" | "vertical") {
|
||||
this._layout.setOrientation(value === "vertical" ? org.nativescript.widgets.Orientation.vertical : org.nativescript.widgets.Orientation.horizontal)
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,19 @@
|
||||
declare module "ui/layouts/stack-layout" {
|
||||
import {LayoutBase} from "ui/layouts/layout-base";
|
||||
import {Property} from "ui/core/dependency-observable";
|
||||
import { LayoutBase, Property } from "ui/layouts/layout-base";
|
||||
|
||||
/**
|
||||
* A Layout that arranges its children horizontally or vertically. The direction can be set by orientation property.
|
||||
*/
|
||||
class StackLayout extends LayoutBase {
|
||||
/**
|
||||
* Represents the observable property backing the orientation property of each StackLayout instance.
|
||||
*/
|
||||
public static orientationProperty: Property;
|
||||
|
||||
/**
|
||||
* Gets or sets if layout should be horizontal or vertical.
|
||||
* The default value is vertical.
|
||||
*/
|
||||
orientation: string;
|
||||
orientation: "horizontal" | "vertical";
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the orientation property of each StackLayout instance.
|
||||
*/
|
||||
export const orientationProperty: Property<StackLayout, "horizontal" | "vertical">;
|
||||
}
|
||||
@@ -1,134 +1,128 @@
|
||||
import common = require("./stack-layout-common");
|
||||
import utils = require("utils/utils");
|
||||
import {View} from "ui/core/view";
|
||||
import {Orientation, VerticalAlignment, HorizontalAlignment} from "ui/enums";
|
||||
import {CommonLayoutParams, nativeLayoutParamsProperty} from "ui/styling/style";
|
||||
import { StackLayoutBase, orientationProperty, View, layout } from "./stack-layout-common";
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
export * from "./stack-layout-common";
|
||||
|
||||
export class StackLayout extends common.StackLayout {
|
||||
export class StackLayout extends StackLayoutBase {
|
||||
private _totalLength = 0;
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
StackLayout.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
var density = utils.layout.getDisplayDensity();
|
||||
|
||||
var measureWidth = 0;
|
||||
var measureHeight = 0;
|
||||
let measureWidth = 0;
|
||||
let measureHeight = 0;
|
||||
|
||||
var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
var isVertical = this.orientation === Orientation.vertical;
|
||||
var verticalPadding = (this.borderTopWidth + this.paddingTop + this.paddingBottom + this.borderBottomWidth) * density;
|
||||
var horizontalPadding = (this.borderLeftWidth + this.paddingLeft + this.paddingRight + this.borderRightWidth) * density;
|
||||
const isVertical = this.orientation === "vertical";
|
||||
const style = this.style;
|
||||
const horizontalPaddingsAndMargins = style.effectivePaddingLeft + style.effectivePaddingRight + style.effectiveBorderLeftWidth + style.effectiveBorderRightWidth;
|
||||
const verticalPaddingsAndMargins = style.effectivePaddingTop + style.effectivePaddingBottom + style.effectiveBorderTopWidth + style.effectiveBorderBottomWidth;
|
||||
|
||||
var measureSpec: number;
|
||||
let measureSpec: number;
|
||||
|
||||
var mode = isVertical ? heightMode : widthMode;
|
||||
var remainingLength: number;
|
||||
let mode = isVertical ? heightMode : widthMode;
|
||||
let remainingLength: number;
|
||||
|
||||
if (mode === utils.layout.UNSPECIFIED) {
|
||||
measureSpec = utils.layout.UNSPECIFIED;
|
||||
if (mode === layout.UNSPECIFIED) {
|
||||
measureSpec = layout.UNSPECIFIED;
|
||||
remainingLength = 0;
|
||||
}
|
||||
else {
|
||||
measureSpec = utils.layout.AT_MOST;
|
||||
remainingLength = isVertical ? height - verticalPadding : width - horizontalPadding;
|
||||
measureSpec = layout.AT_MOST;
|
||||
remainingLength = isVertical ? height - verticalPaddingsAndMargins : width - horizontalPaddingsAndMargins;
|
||||
}
|
||||
|
||||
var childMeasureSpec: number;
|
||||
let childMeasureSpec: number;
|
||||
if (isVertical) {
|
||||
let childWidth = (widthMode === utils.layout.UNSPECIFIED) ? 0 : width - horizontalPadding;
|
||||
let childWidth = (widthMode === layout.UNSPECIFIED) ? 0 : width - horizontalPaddingsAndMargins;
|
||||
childWidth = Math.max(0, childWidth);
|
||||
childMeasureSpec = utils.layout.makeMeasureSpec(childWidth, widthMode)
|
||||
childMeasureSpec = layout.makeMeasureSpec(childWidth, widthMode)
|
||||
}
|
||||
else {
|
||||
let childHeight = (heightMode === utils.layout.UNSPECIFIED) ? 0 : height - verticalPadding;
|
||||
let childHeight = (heightMode === layout.UNSPECIFIED) ? 0 : height - verticalPaddingsAndMargins;
|
||||
childHeight = Math.max(0, childHeight);
|
||||
childMeasureSpec = utils.layout.makeMeasureSpec(childHeight, heightMode)
|
||||
childMeasureSpec = layout.makeMeasureSpec(childHeight, heightMode)
|
||||
}
|
||||
|
||||
var childSize: { measuredWidth: number; measuredHeight: number };
|
||||
let childSize: { measuredWidth: number; measuredHeight: number };
|
||||
|
||||
this.eachLayoutChild((child, last) => {
|
||||
if (isVertical) {
|
||||
childSize = View.measureChild(this, child, childMeasureSpec, utils.layout.makeMeasureSpec(remainingLength, measureSpec));
|
||||
childSize = View.measureChild(this, child, childMeasureSpec, layout.makeMeasureSpec(remainingLength, measureSpec));
|
||||
measureWidth = Math.max(measureWidth, childSize.measuredWidth);
|
||||
var viewHeight = childSize.measuredHeight;
|
||||
let viewHeight = childSize.measuredHeight;
|
||||
measureHeight += viewHeight;
|
||||
remainingLength = Math.max(0, remainingLength - viewHeight);
|
||||
}
|
||||
else {
|
||||
childSize = View.measureChild(this, child, utils.layout.makeMeasureSpec(remainingLength, measureSpec), childMeasureSpec);
|
||||
childSize = View.measureChild(this, child, layout.makeMeasureSpec(remainingLength, measureSpec), childMeasureSpec);
|
||||
measureHeight = Math.max(measureHeight, childSize.measuredHeight);
|
||||
var viewWidth = childSize.measuredWidth;
|
||||
let viewWidth = childSize.measuredWidth;
|
||||
measureWidth += viewWidth;
|
||||
remainingLength = Math.max(0, remainingLength - viewWidth);
|
||||
}
|
||||
});
|
||||
|
||||
measureWidth += horizontalPadding;
|
||||
measureHeight += verticalPadding;
|
||||
measureWidth += horizontalPaddingsAndMargins;
|
||||
measureHeight += verticalPaddingsAndMargins;
|
||||
|
||||
measureWidth = Math.max(measureWidth, this.minWidth * density);
|
||||
measureHeight = Math.max(measureHeight, this.minHeight * density);
|
||||
// Check against our minimum sizes
|
||||
measureWidth = Math.max(measureWidth, style.effectiveMinWidth);
|
||||
measureHeight = Math.max(measureHeight, style.effectiveMinHeight);
|
||||
|
||||
this._totalLength = isVertical ? measureHeight : measureWidth;
|
||||
|
||||
var widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
var heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
super.onLayout(left, top, right, bottom);
|
||||
if (this.orientation === Orientation.vertical) {
|
||||
if (this.orientation === "vertical") {
|
||||
this.layoutVertical(left, top, right, bottom);
|
||||
}
|
||||
else {
|
||||
this.layoutHorizontal(left, top, right, bottom);
|
||||
}
|
||||
|
||||
StackLayout.restoreOriginalParams(this);
|
||||
}
|
||||
|
||||
private layoutVertical(left: number, top: number, right: number, bottom: number): void {
|
||||
var density = utils.layout.getDisplayDensity();
|
||||
var paddingLeft = (this.borderLeftWidth + this.paddingLeft) * density;
|
||||
var paddingRight = (this.borderRightWidth + this.paddingRight) * density;
|
||||
var paddingTop = (this.borderTopWidth + this.paddingTop) * density;
|
||||
var paddingBottom = (this.borderBottomWidth + this.paddingBottom) * density;
|
||||
const style = this.style;
|
||||
const paddingLeft = style.effectiveBorderLeftWidth + style.effectivePaddingLeft;
|
||||
const paddingTop = style.effectiveBorderTopWidth + style.effectivePaddingTop;
|
||||
const paddingRight = style.effectiveBorderRightWidth + style.effectivePaddingRight;
|
||||
const paddingBottom = style.effectiveBorderBottomWidth + style.effectivePaddingBottom;
|
||||
|
||||
var childTop: number;
|
||||
var childLeft: number = paddingLeft;
|
||||
var childRight = right - left - paddingRight;
|
||||
let childTop: number;
|
||||
let childLeft: number = paddingLeft;
|
||||
let childRight = right - left - paddingRight;
|
||||
|
||||
switch (this.verticalAlignment) {
|
||||
case VerticalAlignment.center:
|
||||
case VerticalAlignment.middle:
|
||||
case "center":
|
||||
case "middle":
|
||||
childTop = (bottom - top - this._totalLength) / 2 + paddingTop - paddingBottom;
|
||||
break;
|
||||
|
||||
case VerticalAlignment.bottom:
|
||||
case "bottom":
|
||||
childTop = bottom - top - this._totalLength + paddingTop - paddingBottom;
|
||||
break;
|
||||
|
||||
case VerticalAlignment.top:
|
||||
case VerticalAlignment.stretch:
|
||||
case "top":
|
||||
case "stretch":
|
||||
default:
|
||||
childTop = paddingTop;
|
||||
break;
|
||||
}
|
||||
|
||||
this.eachLayoutChild((child, last) => {
|
||||
let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
|
||||
let childHeight = child.getMeasuredHeight() + (lp.topMargin + lp.bottomMargin) * density;
|
||||
const childStyle = child.style;
|
||||
const childHeight = child.getMeasuredHeight() + childStyle.effectiveMarginTop + childStyle.effectiveMarginBottom;
|
||||
|
||||
View.layoutChild(this, child, childLeft, childTop, childRight, childTop + childHeight);
|
||||
childTop += childHeight;
|
||||
@@ -136,38 +130,38 @@ export class StackLayout extends common.StackLayout {
|
||||
}
|
||||
|
||||
private layoutHorizontal(left: number, top: number, right: number, bottom: number): void {
|
||||
var density = utils.layout.getDisplayDensity();
|
||||
var paddingLeft = (this.borderLeftWidth + this.paddingLeft) * density;
|
||||
var paddingRight = (this.borderRightWidth + this.paddingRight) * density;
|
||||
var paddingTop = (this.borderTopWidth + this.paddingTop) * density;
|
||||
var paddingBottom = (this.borderBottomWidth + this.paddingBottom) * density;
|
||||
const style = this.style;
|
||||
const paddingLeft = style.effectiveBorderLeftWidth + style.effectivePaddingLeft;
|
||||
const paddingTop = style.effectiveBorderTopWidth + style.effectivePaddingTop;
|
||||
const paddingRight = style.effectiveBorderRightWidth + style.effectivePaddingRight;
|
||||
const paddingBottom = style.effectiveBorderBottomWidth + style.effectivePaddingBottom;
|
||||
|
||||
var childTop: number = paddingTop;
|
||||
var childLeft: number;
|
||||
var childBottom = bottom - top - paddingBottom;
|
||||
let childTop: number = paddingTop;
|
||||
let childLeft: number;
|
||||
let childBottom = bottom - top - paddingBottom;
|
||||
|
||||
switch (this.horizontalAlignment) {
|
||||
case HorizontalAlignment.center:
|
||||
case "center":
|
||||
childLeft = (right - left - this._totalLength) / 2 + paddingLeft - paddingRight;
|
||||
break;
|
||||
|
||||
case HorizontalAlignment.right:
|
||||
case "right":
|
||||
childLeft = right - left - this._totalLength + paddingLeft - paddingRight;
|
||||
break;
|
||||
|
||||
case HorizontalAlignment.left:
|
||||
case HorizontalAlignment.stretch:
|
||||
case "left":
|
||||
case "stretch":
|
||||
default:
|
||||
childLeft = paddingLeft;
|
||||
break;
|
||||
}
|
||||
|
||||
this.eachLayoutChild((child, last) => {
|
||||
let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
|
||||
let childWidth = child.getMeasuredWidth() + (lp.leftMargin + lp.rightMargin) * density;
|
||||
const childStyle = child.style;
|
||||
const childWidth = child.getMeasuredWidth() + childStyle.effectiveMarginLeft + childStyle.effectiveMarginRight;
|
||||
|
||||
View.layoutChild(this, child, childLeft, childTop, childLeft + childWidth, childBottom);
|
||||
childLeft += childWidth;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,36 @@
|
||||
import definition = require("ui/layouts/wrap-layout");
|
||||
import platform = require("platform");
|
||||
import {LayoutBase} from "ui/layouts/layout-base";
|
||||
import {Orientation} from "ui/enums";
|
||||
import {PropertyMetadata} from "ui/core/proxy";
|
||||
import {Property, PropertyMetadataSettings} from "ui/core/dependency-observable";
|
||||
import { WrapLayout as WrapLayoutDefinition } from "ui/layouts/wrap-layout";
|
||||
import { LayoutBase, Property, isIOS, Length, zeroLength, getLengthEffectiveValue } from "ui/layouts/layout-base";
|
||||
|
||||
// on Android we explicitly set propertySettings to None because android will invalidate its layout (so we skip unnecessary native call).
|
||||
var AffectsLayout = platform.device.os === platform.platformNames.android ? PropertyMetadataSettings.None : PropertyMetadataSettings.AffectsLayout;
|
||||
export * from "ui/layouts/layout-base";
|
||||
|
||||
function isWidthHeightValid(value: any): boolean {
|
||||
return (value >= 0.0 && value !== Number.POSITIVE_INFINITY);
|
||||
export class WrapLayoutBase extends LayoutBase implements WrapLayoutDefinition {
|
||||
public orientation: "horizontal" | "vertical";
|
||||
public itemWidth: Length;
|
||||
public itemHeight: Length;
|
||||
public effectiveItemWidth: number;
|
||||
public effectiveItemHeight: number;
|
||||
}
|
||||
|
||||
function isValidOrientation(value: any): boolean {
|
||||
return value === Orientation.vertical || value === Orientation.horizontal;
|
||||
}
|
||||
export const itemWidthProperty = new Property<WrapLayoutBase, Length>({
|
||||
name: "itemWidth", defaultValue: zeroLength, affectsLayout: isIOS, valueConverter: (v) => Length.parse(v),
|
||||
valueChanged: (target, oldValue, newValue) => target.effectiveItemWidth = getLengthEffectiveValue(newValue)
|
||||
});
|
||||
itemWidthProperty.register(WrapLayoutBase);
|
||||
|
||||
export class WrapLayout extends LayoutBase implements definition.WrapLayout {
|
||||
public static orientationProperty = new Property("orientation", "WrapLayout", new PropertyMetadata(Orientation.horizontal, AffectsLayout, undefined, isValidOrientation));
|
||||
public static itemWidthProperty = new Property("itemWidth", "WrapLayout", new PropertyMetadata(0, AffectsLayout, undefined, isWidthHeightValid));
|
||||
public static itemHeightProperty = new Property("itemHeight", "WrapLayout", new PropertyMetadata(0, AffectsLayout, undefined, isWidthHeightValid));
|
||||
export const itemHeightProperty = new Property<WrapLayoutBase, Length>({
|
||||
name: "itemHeight", defaultValue: zeroLength, affectsLayout: isIOS, valueConverter: (v) => Length.parse(v),
|
||||
valueChanged: (target, oldValue, newValue) => target.effectiveItemHeight = getLengthEffectiveValue(newValue)
|
||||
});
|
||||
itemHeightProperty.register(WrapLayoutBase);
|
||||
|
||||
get orientation(): string {
|
||||
return this._getValue(WrapLayout.orientationProperty);
|
||||
}
|
||||
set orientation(value: string) {
|
||||
this._setValue(WrapLayout.orientationProperty, value);
|
||||
}
|
||||
export const orientationProperty = new Property<WrapLayoutBase, "horizontal" | "vertical">({
|
||||
name: "orientation", defaultValue: "horizontal", affectsLayout: isIOS,
|
||||
valueConverter: (v) => {
|
||||
if (v === "horizontal" || v === "vertical") {
|
||||
return <"horizontal" | "vertical">v;
|
||||
}
|
||||
|
||||
get itemWidth(): number {
|
||||
return this._getValue(WrapLayout.itemWidthProperty);
|
||||
throw new Error(`Invalid orientation value: ${v}`);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
orientationProperty.register(WrapLayoutBase);
|
||||
@@ -1,34 +1,8 @@
|
||||
import utils = require("utils/utils");
|
||||
import common = require("./wrap-layout-common");
|
||||
import {Orientation} from "ui/enums";
|
||||
import {PropertyMetadata} from "ui/core/proxy";
|
||||
import {PropertyChangeData} from "ui/core/dependency-observable";
|
||||
import { WrapLayoutBase, orientationProperty, itemWidthProperty, itemHeightProperty } from "./wrap-layout-common";
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
export * from "./wrap-layout-common";
|
||||
|
||||
function setNativeOrientationProperty(data: PropertyChangeData): void {
|
||||
var wrapLayout = <WrapLayout>data.object;
|
||||
var nativeView = wrapLayout._nativeView;
|
||||
nativeView.setOrientation(data.newValue === Orientation.vertical ? org.nativescript.widgets.Orientation.vertical : org.nativescript.widgets.Orientation.horizontal);
|
||||
}
|
||||
|
||||
function setNativeItemWidthProperty(data: PropertyChangeData): void {
|
||||
var wrapLayout = <WrapLayout>data.object;
|
||||
var nativeView = wrapLayout._nativeView;
|
||||
nativeView.setItemWidth(data.newValue * utils.layout.getDisplayDensity());
|
||||
}
|
||||
|
||||
function setNativeItemHeightProperty(data: PropertyChangeData): void {
|
||||
var wrapLayout = <WrapLayout>data.object;
|
||||
var nativeView = wrapLayout._nativeView;
|
||||
nativeView.setItemHeight(data.newValue * utils.layout.getDisplayDensity());
|
||||
}
|
||||
|
||||
(<PropertyMetadata>common.WrapLayout.orientationProperty.metadata).onSetNativeValue = setNativeOrientationProperty;
|
||||
(<PropertyMetadata>common.WrapLayout.itemWidthProperty.metadata).onSetNativeValue = setNativeItemWidthProperty;
|
||||
(<PropertyMetadata>common.WrapLayout.itemHeightProperty.metadata).onSetNativeValue = setNativeItemHeightProperty;
|
||||
|
||||
export class WrapLayout extends common.WrapLayout {
|
||||
export class WrapLayout extends WrapLayoutBase {
|
||||
private _layout: org.nativescript.widgets.WrapLayout;
|
||||
|
||||
get android(): org.nativescript.widgets.WrapLayout {
|
||||
@@ -42,4 +16,25 @@ export class WrapLayout extends common.WrapLayout {
|
||||
public _createUI() {
|
||||
this._layout = new org.nativescript.widgets.WrapLayout(this._context);
|
||||
}
|
||||
|
||||
get [orientationProperty.native](): "horizontal" | "vertical" {
|
||||
return "vertical";
|
||||
}
|
||||
set [orientationProperty.native](value: "horizontal" | "vertical") {
|
||||
this._layout.setOrientation(value === "vertical" ? org.nativescript.widgets.Orientation.vertical : org.nativescript.widgets.Orientation.horizontal)
|
||||
}
|
||||
|
||||
get [itemWidthProperty.native](): number {
|
||||
return 0;
|
||||
}
|
||||
set [itemWidthProperty.native](value: number) {
|
||||
this._layout.setItemWidth(this.effectiveItemWidth);
|
||||
}
|
||||
|
||||
get [itemHeightProperty.native](): number {
|
||||
return 0;
|
||||
}
|
||||
set [itemHeightProperty.native](value: number) {
|
||||
this._layout.setItemHeight(this.effectiveItemHeight);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
declare module "ui/layouts/wrap-layout" {
|
||||
import {LayoutBase} from "ui/layouts/layout-base";
|
||||
import {Property} from "ui/core/dependency-observable";
|
||||
import { LayoutBase, Property, Length } from "ui/layouts/layout-base";
|
||||
|
||||
/**
|
||||
* WrapLayout position children in rows or columns depending on orientation property
|
||||
@@ -8,37 +7,37 @@
|
||||
*/
|
||||
class WrapLayout extends LayoutBase {
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the orientation property of each WrapLayout instance.
|
||||
*/
|
||||
public static orientationProperty: Property;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the itemWidth property of each WrapLayout instance.
|
||||
*/
|
||||
public static itemWidthProperty: Property;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the itemHeight property of each WrapLayout instance.
|
||||
*/
|
||||
public static itemHeightProperty: Property;
|
||||
|
||||
/**
|
||||
* Gets or sets the flow direction. Default value is horizontal.
|
||||
* If orientation is horizontal items are arranged in rows, else items are arranged in columns.
|
||||
*/
|
||||
orientation: string;
|
||||
orientation: "horizontal" | "vertical";
|
||||
|
||||
/**
|
||||
* Gets or sets the width used to measure and layout each child.
|
||||
* Default value is Number.NaN which does not restrict children.
|
||||
*/
|
||||
itemWidth: number;
|
||||
|
||||
itemWidth: Length;
|
||||
|
||||
/**
|
||||
* Gets or sets the height used to measure and layout each child.
|
||||
* Default value is Number.NaN which does not restrict children.
|
||||
*/
|
||||
itemHeight: number;
|
||||
itemHeight: Length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the orientation property of each WrapLayout instance.
|
||||
*/
|
||||
export const orientationProperty: Property<WrapLayout, "horizontal" | "vertical">;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the itemWidth property of each WrapLayout instance.
|
||||
*/
|
||||
export const itemWidthProperty: Property<WrapLayout, Length>;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the itemHeight property of each WrapLayout instance.
|
||||
*/
|
||||
export const itemHeightProperty: Property<WrapLayout, Length>;
|
||||
}
|
||||
@@ -1,63 +1,60 @@
|
||||
import utils = require("utils/utils");
|
||||
import common = require("./wrap-layout-common");
|
||||
import {View} from "ui/core/view";
|
||||
import {Orientation} from "ui/enums";
|
||||
import {CommonLayoutParams, nativeLayoutParamsProperty} from "ui/styling/style";
|
||||
import { WrapLayoutBase, View, orientationProperty, itemWidthProperty, itemHeightProperty, layout } from "./wrap-layout-common";
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
export * from "./wrap-layout-common";
|
||||
|
||||
export class WrapLayout extends common.WrapLayout {
|
||||
export class WrapLayout extends WrapLayoutBase {
|
||||
private _lengths: Array<number> = new Array<number>();
|
||||
|
||||
private static getChildMeasureSpec(parentMode: number, parentLength: number, itemLength): number {
|
||||
if (itemLength > 0) {
|
||||
return utils.layout.makeMeasureSpec(itemLength, utils.layout.EXACTLY);
|
||||
return layout.makeMeasureSpec(itemLength, layout.EXACTLY);
|
||||
}
|
||||
else if (parentMode === utils.layout.UNSPECIFIED) {
|
||||
return utils.layout.makeMeasureSpec(0, utils.layout.UNSPECIFIED);
|
||||
else if (parentMode === layout.UNSPECIFIED) {
|
||||
return layout.makeMeasureSpec(0, layout.UNSPECIFIED);
|
||||
}
|
||||
else {
|
||||
return utils.layout.makeMeasureSpec(parentLength, utils.layout.AT_MOST);
|
||||
return layout.makeMeasureSpec(parentLength, layout.AT_MOST);
|
||||
}
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
WrapLayout.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
var measureWidth = 0;
|
||||
var measureHeight = 0;
|
||||
let measureWidth = 0;
|
||||
let measureHeight = 0;
|
||||
|
||||
var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
var density = utils.layout.getDisplayDensity();
|
||||
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
var horizontalPadding = (this.borderLeftWidth + this.paddingLeft + this.paddingRight + this.borderRightWidth) * density;
|
||||
var verticalPadding = (this.borderTopWidth + this.paddingTop + this.paddingBottom + this.borderBottomWidth) * density;
|
||||
const style = this.style;
|
||||
const horizontalPaddingsAndMargins = style.effectivePaddingLeft + style.effectivePaddingRight + style.effectiveBorderLeftWidth + style.effectiveBorderRightWidth;
|
||||
const verticalPaddingsAndMargins = style.effectivePaddingTop + style.effectivePaddingBottom + style.effectiveBorderTopWidth + style.effectiveBorderBottomWidth;
|
||||
|
||||
var availableWidth = widthMode === utils.layout.UNSPECIFIED ? Number.MAX_VALUE : utils.layout.getMeasureSpecSize(widthMeasureSpec) - horizontalPadding;
|
||||
var availableHeight = heightMode === utils.layout.UNSPECIFIED ? Number.MAX_VALUE : utils.layout.getMeasureSpecSize(heightMeasureSpec) - verticalPadding;
|
||||
const availableWidth = widthMode === layout.UNSPECIFIED ? Number.MAX_VALUE : width - horizontalPaddingsAndMargins;
|
||||
const availableHeight = heightMode === layout.UNSPECIFIED ? Number.MAX_VALUE : height - verticalPaddingsAndMargins;
|
||||
|
||||
var childWidthMeasureSpec: number = WrapLayout.getChildMeasureSpec(widthMode, availableWidth, this.itemWidth * density);
|
||||
var childHeightMeasureSpec: number = WrapLayout.getChildMeasureSpec(heightMode, availableHeight, this.itemHeight * density);
|
||||
const childWidthMeasureSpec: number = WrapLayout.getChildMeasureSpec(widthMode, availableWidth, this.effectiveItemWidth);
|
||||
const childHeightMeasureSpec: number = WrapLayout.getChildMeasureSpec(heightMode, availableHeight, this.effectiveItemHeight);
|
||||
|
||||
var remainingWidth = availableWidth;
|
||||
var remainingHeight = availableHeight;
|
||||
let remainingWidth = availableWidth;
|
||||
let remainingHeight = availableHeight;
|
||||
|
||||
this._lengths.length = 0;
|
||||
var rowOrColumn = 0;
|
||||
var maxLength = 0;
|
||||
|
||||
var isVertical = this.orientation === Orientation.vertical;
|
||||
var isVertical = this.orientation === "vertical";
|
||||
|
||||
let useItemWidth: boolean = this.itemWidth > 0;
|
||||
let useItemHeight: boolean = this.itemHeight > 0;
|
||||
let itemWidth = this.itemWidth;
|
||||
let itemHeight = this.itemHeight;
|
||||
let useItemWidth: boolean = this.effectiveItemWidth > 0;
|
||||
let useItemHeight: boolean = this.effectiveItemHeight > 0;
|
||||
let itemWidth = this.effectiveItemWidth;
|
||||
let itemHeight = this.effectiveItemHeight;
|
||||
|
||||
this.eachLayoutChild((child, last) => {
|
||||
var desiredSize = View.measureChild(this, child, childWidthMeasureSpec, childHeightMeasureSpec);
|
||||
const desiredSize = View.measureChild(this, child, childWidthMeasureSpec, childHeightMeasureSpec);
|
||||
let childMeasuredWidth = useItemWidth ? itemWidth : desiredSize.measuredWidth;
|
||||
let childMeasuredHeight = useItemHeight ? itemHeight : desiredSize.measuredHeight;
|
||||
let isFirst = this._lengths.length <= rowOrColumn;
|
||||
@@ -110,14 +107,15 @@ export class WrapLayout extends common.WrapLayout {
|
||||
});
|
||||
}
|
||||
|
||||
measureWidth += horizontalPadding;
|
||||
measureHeight += verticalPadding;
|
||||
measureWidth += horizontalPaddingsAndMargins;
|
||||
measureHeight += verticalPaddingsAndMargins;
|
||||
|
||||
measureWidth = Math.max(measureWidth, this.minWidth * density);
|
||||
measureHeight = Math.max(measureHeight, this.minHeight * density);
|
||||
// Check against our minimum sizes
|
||||
measureWidth = Math.max(measureWidth, style.effectiveMinWidth);
|
||||
measureHeight = Math.max(measureHeight, style.effectiveMinHeight);
|
||||
|
||||
var widthAndState = View.resolveSizeAndState(measureWidth, utils.layout.getMeasureSpecSize(widthMeasureSpec), widthMode, 0);
|
||||
var heightAndState = View.resolveSizeAndState(measureHeight, utils.layout.getMeasureSpecSize(heightMeasureSpec), heightMode, 0);
|
||||
const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
@@ -125,45 +123,42 @@ export class WrapLayout extends common.WrapLayout {
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
super.onLayout(left, top, right, bottom);
|
||||
|
||||
var isVertical = this.orientation === Orientation.vertical;
|
||||
const isVertical = this.orientation === "vertical";
|
||||
const style = this.style;
|
||||
const paddingLeft = style.effectiveBorderLeftWidth + style.effectivePaddingLeft;
|
||||
const paddingTop = style.effectiveBorderTopWidth + style.effectivePaddingTop;
|
||||
const paddingRight = style.effectiveBorderRightWidth + style.effectivePaddingRight;
|
||||
const paddingBottom = style.effectiveBorderBottomWidth + style.effectivePaddingBottom;
|
||||
|
||||
var density = utils.layout.getDisplayDensity();
|
||||
|
||||
const topPadding = (this.borderTopWidth + this.paddingTop) * density;
|
||||
const leftPadding = (this.borderLeftWidth + this.paddingLeft) * density;
|
||||
const bottomPadding = (this.paddingBottom + this.borderBottomWidth) * density;
|
||||
const rightPadding = (this.paddingRight + this.borderRightWidth) * density;
|
||||
|
||||
var childLeft = leftPadding;
|
||||
var childTop = topPadding;
|
||||
var childrenLength: number;
|
||||
let childLeft = paddingLeft;
|
||||
let childTop = paddingTop;
|
||||
let childrenLength: number;
|
||||
if (isVertical) {
|
||||
childrenLength = bottom - top - bottomPadding;
|
||||
childrenLength = bottom - top - paddingBottom;
|
||||
}
|
||||
else {
|
||||
childrenLength = right - left - rightPadding;
|
||||
childrenLength = right - left - paddingRight;
|
||||
}
|
||||
|
||||
var rowOrColumn = 0;
|
||||
this.eachLayoutChild((child, last) => {
|
||||
// Add margins because layoutChild will sustract them.
|
||||
// * density converts them to device pixels.
|
||||
let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
|
||||
|
||||
let childWidth = child.getMeasuredWidth() + (lp.leftMargin + lp.rightMargin) * density;
|
||||
let childHeight = child.getMeasuredHeight() + (lp.topMargin + lp.bottomMargin) * density;
|
||||
|
||||
const childStyle = child.style;
|
||||
let childHeight = child.getMeasuredHeight() + childStyle.effectiveMarginTop + childStyle.effectiveMarginBottom;
|
||||
let childWidth = child.getMeasuredWidth() + childStyle.effectiveMarginLeft + childStyle.effectiveMarginRight;
|
||||
|
||||
let length = this._lengths[rowOrColumn];
|
||||
if (isVertical) {
|
||||
childWidth = length;
|
||||
childHeight = this.itemHeight > 0 ? this.itemHeight * density : childHeight;
|
||||
let isFirst = childTop === topPadding;
|
||||
childHeight = this.effectiveItemHeight > 0 ? this.effectiveItemHeight : childHeight;
|
||||
let isFirst = childTop === paddingTop;
|
||||
if (childTop + childHeight > childrenLength) {
|
||||
// Move to top.
|
||||
childTop = topPadding;
|
||||
childTop = paddingTop;
|
||||
|
||||
if (!isFirst) {
|
||||
// Move to right with current column width.
|
||||
// Move to right with current column width.
|
||||
childLeft += length;
|
||||
}
|
||||
|
||||
@@ -175,12 +170,12 @@ export class WrapLayout extends common.WrapLayout {
|
||||
}
|
||||
}
|
||||
else {
|
||||
childWidth = this.itemWidth > 0 ? this.itemWidth * density : childWidth;
|
||||
childWidth = this.effectiveItemWidth > 0 ? this.effectiveItemWidth : childWidth;
|
||||
childHeight = length;
|
||||
let isFirst = childLeft === leftPadding;
|
||||
let isFirst = childLeft === paddingLeft;
|
||||
if (childLeft + childWidth > childrenLength) {
|
||||
// Move to left.
|
||||
childLeft = leftPadding;
|
||||
childLeft = paddingLeft;
|
||||
|
||||
if (!isFirst) {
|
||||
// Move to bottom with current row height.
|
||||
@@ -206,7 +201,5 @@ export class WrapLayout extends common.WrapLayout {
|
||||
childLeft += childWidth;
|
||||
}
|
||||
});
|
||||
|
||||
WrapLayout.restoreOriginalParams(this);
|
||||
}
|
||||
}
|
||||
@@ -3,56 +3,6 @@
|
||||
|
||||
export * from "./utils-common";
|
||||
|
||||
export module layout {
|
||||
var density = -1;
|
||||
var metrics: android.util.DisplayMetrics;
|
||||
|
||||
// cache the MeasureSpec constants here, to prevent extensive marshaling calls to and from Java
|
||||
// TODO: While this boosts the performance it is error-prone in case Google changes these constants
|
||||
var MODE_SHIFT = 30;
|
||||
var MODE_MASK = 0x3 << MODE_SHIFT;
|
||||
var sdkVersion = -1;
|
||||
var useOldMeasureSpec = false;
|
||||
|
||||
export function makeMeasureSpec(size: number, mode: number): number {
|
||||
if (sdkVersion === -1) {
|
||||
// check whether the old layout is needed
|
||||
sdkVersion = ad.getApplicationContext().getApplicationInfo().targetSdkVersion;
|
||||
useOldMeasureSpec = sdkVersion <= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
|
||||
}
|
||||
|
||||
if (useOldMeasureSpec) {
|
||||
return size + mode;
|
||||
}
|
||||
|
||||
return (size & ~MODE_MASK) | (mode & MODE_MASK);
|
||||
}
|
||||
|
||||
export function getDisplayMetrics(): android.util.DisplayMetrics {
|
||||
if (!metrics) {
|
||||
metrics = ad.getApplicationContext().getResources().getDisplayMetrics();
|
||||
}
|
||||
|
||||
return metrics;
|
||||
}
|
||||
|
||||
export function getDisplayDensity(): number {
|
||||
if (density === -1) {
|
||||
density = getDisplayMetrics().density;
|
||||
}
|
||||
|
||||
return density;
|
||||
}
|
||||
|
||||
export function toDevicePixels(value: number): number {
|
||||
return value * getDisplayDensity();
|
||||
}
|
||||
|
||||
export function toDeviceIndependentPixels(value: number): number {
|
||||
return value / getDisplayDensity();
|
||||
}
|
||||
}
|
||||
|
||||
// We are using "ad" here to avoid namespace collision with the global android object
|
||||
export module ad {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user