diff --git a/CrossPlatformModules.csproj b/CrossPlatformModules.csproj
index 72a63583b..ee9f7bcc8 100644
--- a/CrossPlatformModules.csproj
+++ b/CrossPlatformModules.csproj
@@ -80,6 +80,7 @@
data-binding.xml
+
modal-page.xml
diff --git a/apps/tests/layouts/absolute-layout-tests.ts b/apps/tests/layouts/absolute-layout-tests.ts
index 8c28fb3f6..8fadba0d0 100644
--- a/apps/tests/layouts/absolute-layout-tests.ts
+++ b/apps/tests/layouts/absolute-layout-tests.ts
@@ -99,6 +99,27 @@ export class AbsoluteLayoutTest extends testModule.UITestbtn).width = "50%";
+ (btn).height = "50%";
+ btn.margin = "10%";
+ layout.addChild(btn);
+
+ this.waitUntilTestElementLayoutIsValid();
+
+ // AbsoluteLayout measures with 0/UNSPECIFIED so we cannot support percents in it.
+ layoutHelper.assertMeasure(btn, 100, 100);
+ layoutHelper.assertLayout(btn, 20, 20, btn.getMeasuredWidth(), btn.getMeasuredHeight());
+
+ TKUnit.assertEqual(btn.getMeasuredWidth(), 100, "Button MeasuredWidth incorrect");
+ TKUnit.assertEqual(btn.getMeasuredHeight(), 100, "Button MeasuredHeight incorrect");
+ }
}
export function createTestCase(): AbsoluteLayoutTest {
diff --git a/apps/tests/layouts/common-layout-tests.ts b/apps/tests/layouts/common-layout-tests.ts
new file mode 100644
index 000000000..c7693eea0
--- /dev/null
+++ b/apps/tests/layouts/common-layout-tests.ts
@@ -0,0 +1,86 @@
+import TKUnit = require("../TKUnit");
+import layoutHelper = require("./layout-helper");
+import enums = require("ui/enums");
+import testModule = require("../ui-test");
+import {LayoutBase} from "ui/layouts/layout-base";
+import {widthProperty} from "ui/styling/style"
+
+export function percent_support_test(test: testModule.UITest) {
+ let layout: LayoutBase = test.testView;
+ layout.removeChildren();
+ layout.width = layoutHelper.dp(200);
+ layout.height = layoutHelper.dp(200);
+
+ let btn = new layoutHelper.MyButton();
+ btn.horizontalAlignment = enums.HorizontalAlignment.left;
+ btn.verticalAlignment = enums.VerticalAlignment.top;
+ (btn).width = "50%";
+ (btn).height = "50%";
+ btn.margin = "10%";
+ btn.text = "1";
+ layout.addChild(btn);
+
+ test.waitUntilTestElementLayoutIsValid();
+
+ TKUnit.assertEqual(btn.getMeasuredWidth(), 100, "Button MeasuredWidth incorrect");
+ TKUnit.assertEqual(btn.getMeasuredHeight(), 100, "Button MeasuredHeight incorrect");
+
+ let bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 20, "TopLeft layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 20, "TopLeft layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 120, "TopLeft layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 120, "TopLeft layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.center;
+ btn.verticalAlignment = enums.VerticalAlignment.center;
+ test.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 50, "Center layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 50, "Center layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 150, "Center layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 150, "Center layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.stretch;
+ btn.verticalAlignment = enums.VerticalAlignment.stretch;
+ test.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 50, "Stretch layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 50, "Stretch layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 150, "Stretch layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 150, "Stretch layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.right;
+ btn.verticalAlignment = enums.VerticalAlignment.bottom;
+ test.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 200 - 100 - 20, "BottomRight layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 200 - 100 - 20, "BottomRight layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 200 - 20, "BottomRight layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 200 - 20, "BottomRight layout BOTTOM incorrect");
+
+ //reset values.
+ btn.height = Number.NaN;
+ (btn.style)._resetValue(widthProperty);
+ btn.margin = "0";
+ btn.horizontalAlignment = enums.HorizontalAlignment.stretch;
+ btn.verticalAlignment = enums.VerticalAlignment.stretch;
+ btn.height = Number.NaN;
+
+ TKUnit.assertEqual(btn.marginLeft, 0, "marginLeft");
+ TKUnit.assertEqual(btn.marginTop, 0, "marginTop");
+ TKUnit.assertEqual(btn.marginRight, 0, "marginRight");
+ TKUnit.assertEqual(btn.marginBottom, 0, "marginBottom");
+ TKUnit.assert(isNaN(btn.width), "width");
+ TKUnit.assert(isNaN(btn.height), "height");
+
+ test.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 0, "Reset Stretch layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 0, "Reset Stretch layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 200, "Reset Stretch layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 200, "Reset Stretch layout BOTTOM incorrect");
+}
\ No newline at end of file
diff --git a/apps/tests/layouts/dock-layout-tests.ts b/apps/tests/layouts/dock-layout-tests.ts
index 4e7e69dc8..141a7bade 100644
--- a/apps/tests/layouts/dock-layout-tests.ts
+++ b/apps/tests/layouts/dock-layout-tests.ts
@@ -6,6 +6,7 @@ import helper = require("./layout-helper");
import navHelper = require("../ui/helper");
import testModule = require("../ui-test");
import layoutHelper = require("./layout-helper");
+import commonTests = require("./common-layout-tests");
//
// # DockLayout
@@ -190,6 +191,10 @@ export class DockLayoutTest extends testModule.UITest {
// ```
//
}
+
+ public test_percent_support() {
+ commonTests.percent_support_test(this);
+ }
}
export function createTestCase(): DockLayoutTest {
diff --git a/apps/tests/layouts/grid-layout-tests.ts b/apps/tests/layouts/grid-layout-tests.ts
index 625891517..e4fd393c4 100644
--- a/apps/tests/layouts/grid-layout-tests.ts
+++ b/apps/tests/layouts/grid-layout-tests.ts
@@ -11,6 +11,7 @@ import enums = require("ui/enums");
import testModule = require("../ui-test");
import layoutHelper = require("./layout-helper");
import platform = require("platform");
+import commonTests = require("./common-layout-tests");
var DELTA = 1;
@@ -641,6 +642,10 @@ export class GridLayoutTest extends testModule.UITest {
// ```
//
}
+
+ public test_percent_support() {
+ commonTests.percent_support_test(this);
+ }
}
export function createTestCase(): GridLayoutTest {
diff --git a/apps/tests/layouts/stack-layout-tests.ts b/apps/tests/layouts/stack-layout-tests.ts
index 8ec4bab73..279fbd94c 100644
--- a/apps/tests/layouts/stack-layout-tests.ts
+++ b/apps/tests/layouts/stack-layout-tests.ts
@@ -8,6 +8,7 @@ import enums = require("ui/enums");
import utils = require("utils/utils");
import testModule = require("../ui-test");
import layoutHelper = require("./layout-helper");
+import commonTests = require("./common-layout-tests");
export class StackLayoutTest extends testModule.UITest {
@@ -204,6 +205,113 @@ export class StackLayoutTest extends testModule.UITest {
//
}
+
+ private setup_percent(): layoutHelper.MyButton {
+ let layout = this.testView;
+ layout.removeChildren();
+ layout.width = layoutHelper.dp(200);
+ layout.height = layoutHelper.dp(200);
+
+ let btn = new layoutHelper.MyButton();
+ btn.horizontalAlignment = enums.HorizontalAlignment.left;
+ btn.verticalAlignment = enums.VerticalAlignment.top;
+ (btn).width = "50%";
+ (btn).height = "50%";
+ btn.margin = "10%";
+ btn.text = "1";
+ layout.addChild(btn);
+ return btn;
+ }
+
+ public test_percent_support_vertical() {
+ let btn = this.setup_percent();
+
+ this.waitUntilTestElementLayoutIsValid();
+
+ TKUnit.assertEqual(btn.getMeasuredWidth(), 100, "Button MeasuredWidth incorrect");
+ TKUnit.assertEqual(btn.getMeasuredHeight(), 100, "Button MeasuredHeight incorrect");
+
+ let bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 20, "TopLeft layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 20, "TopLeft layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 120, "TopLeft layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 120, "TopLeft layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.center;
+ btn.verticalAlignment = enums.VerticalAlignment.center;
+ this.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 50, "Center layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 20, "Center layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 150, "Center layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 120, "Center layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.stretch;
+ btn.verticalAlignment = enums.VerticalAlignment.stretch;
+ this.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 50, "Stretch layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 20, "Stretch layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 150, "Stretch layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 120, "Stretch layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.right;
+ btn.verticalAlignment = enums.VerticalAlignment.bottom;
+ this.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 80, "BottomRight layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 20, "BottomRight layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 180, "BottomRight layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 120, "BottomRight layout BOTTOM incorrect");
+ }
+
+ public test_percent_support_horizontal() {
+ let btn = this.setup_percent();
+ this.testView.orientation = enums.Orientation.horizontal;
+ this.waitUntilTestElementLayoutIsValid();
+
+ TKUnit.assertEqual(btn.getMeasuredWidth(), 100, "Button MeasuredWidth incorrect");
+ TKUnit.assertEqual(btn.getMeasuredHeight(), 100, "Button MeasuredHeight incorrect");
+
+ let bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 20, "TopLeft layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 20, "TopLeft layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 120, "TopLeft layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 120, "TopLeft layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.center;
+ btn.verticalAlignment = enums.VerticalAlignment.center;
+ this.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 20, "Center layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 50, "Center layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 120, "Center layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 150, "Center layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.stretch;
+ btn.verticalAlignment = enums.VerticalAlignment.stretch;
+ this.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 20, "Stretch layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 50, "Stretch layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 120, "Stretch layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 150, "Stretch layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.right;
+ btn.verticalAlignment = enums.VerticalAlignment.bottom;
+ this.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 20, "BottomRight layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 80, "BottomRight layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 120, "BottomRight layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 180, "BottomRight layout BOTTOM incorrect");
+ }
}
export function createTestCase(): StackLayoutTest {
diff --git a/apps/tests/layouts/wrap-layout-tests.ts b/apps/tests/layouts/wrap-layout-tests.ts
index 23f042e13..7d0c9868d 100644
--- a/apps/tests/layouts/wrap-layout-tests.ts
+++ b/apps/tests/layouts/wrap-layout-tests.ts
@@ -1,9 +1,9 @@
import TKUnit = require("../TKUnit");
-import viewModule = require("ui/core/view");
-import labelModule = require("ui/label");
+import {Label} from "ui/label";
import helper = require("../ui/helper");
import layoutHelper = require("./layout-helper");
import testModule = require("../ui-test");
+import commonTests = require("./common-layout-tests");
//
// # WrapLayout
@@ -47,7 +47,7 @@ export class WrapLayoutTest extends testModule.UITestbtn).width = "50%";
+ (btn).height = "50%";
+ btn.margin = "10%";
+ btn.text = "1";
+ layout.addChild(btn);
+
+ this.waitUntilTestElementLayoutIsValid();
+
+ TKUnit.assertEqual(btn.getMeasuredWidth(), 100, "Button MeasuredWidth incorrect");
+ TKUnit.assertEqual(btn.getMeasuredHeight(), 100, "Button MeasuredHeight incorrect");
+
+ let bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 20, "TopLeft layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 20, "TopLeft layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 120, "TopLeft layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 120, "TopLeft layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.center;
+ btn.verticalAlignment = enums.VerticalAlignment.center;
+ this.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 20, "Center layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 20, "Center layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 120, "Center layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 120, "Center layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.stretch;
+ btn.verticalAlignment = enums.VerticalAlignment.stretch;
+ this.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 20, "Stretch layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 20, "Stretch layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 120, "Stretch layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 120, "Stretch layout BOTTOM incorrect");
+
+ btn.horizontalAlignment = enums.HorizontalAlignment.right;
+ btn.verticalAlignment = enums.VerticalAlignment.bottom;
+ this.waitUntilTestElementLayoutIsValid();
+
+ bounds = btn._getCurrentLayoutBounds();
+ TKUnit.assertEqual(bounds.left, 20, "BottomRight layout LEFT incorrect");
+ TKUnit.assertEqual(bounds.top, 20, "BottomRight layout TOP incorrect");
+ TKUnit.assertEqual(bounds.right, 120, "BottomRight layout RIGHT incorrect");
+ TKUnit.assertEqual(bounds.bottom, 120, "BottomRight layout BOTTOM incorrect");
+ }
}
export function createTestCase(): WrapLayoutTest {
diff --git a/org.nativescript.widgets.d.ts b/org.nativescript.widgets.d.ts
index da1b342d8..6dfbc4998 100644
--- a/org.nativescript.widgets.d.ts
+++ b/org.nativescript.widgets.d.ts
@@ -4,6 +4,14 @@
export class CommonLayoutParams extends android.widget.FrameLayout.LayoutParams {
constructor();
+ public widthPercent: number;
+ public heightPercent: number;
+
+ public topMarginPercent: number;
+ public leftMarginPercent: number;
+ public bottomMarginPercent: number;
+ public rightMarginPercent: number;
+
public left: number;
public top: number;
diff --git a/trace/trace.ts b/trace/trace.ts
index 4398c4e36..7d8173771 100644
--- a/trace/trace.ts
+++ b/trace/trace.ts
@@ -38,10 +38,7 @@ export function setCategories(categories: string) {
export function addCategories(categories: string) {
var split = categories.split(",");
- _categories = {};
-
- var i;
- for (i = 0; i < split.length; i++) {
+ for (let i = 0; i < split.length; i++) {
_categories[split[i].trim()] = true;
}
}
diff --git a/tsconfig.json b/tsconfig.json
index 97427c6cf..93f0a4aa5 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -169,6 +169,7 @@
"apps/tests/http-tests.ts",
"apps/tests/image-source-tests.ts",
"apps/tests/layouts/absolute-layout-tests.ts",
+ "apps/tests/layouts/common-layout-tests.ts",
"apps/tests/layouts/dock-layout-tests.ts",
"apps/tests/layouts/grid-layout-tests.ts",
"apps/tests/layouts/layout-helper.android.ts",
diff --git a/ui/core/view-common.ts b/ui/core/view-common.ts
index 9a5f69105..eb4a7373c 100644
--- a/ui/core/view-common.ts
+++ b/ui/core/view-common.ts
@@ -15,6 +15,7 @@ import color = require("color");
import animationModule = require("ui/animation");
import observable = require("data/observable");
import {registerSpecialProperty} from "ui/builder/special-properties";
+import {CommonLayoutParams, nativeLayoutParamsProperty} from "ui/styling/style";
registerSpecialProperty("class", (instance: definition.View, propertyValue: string) => {
instance.className = propertyValue;
@@ -727,6 +728,7 @@ export class View extends proxy.ProxyObject implements definition.View {
}
var density = utils.layout.getDisplayDensity();
+ let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
var childTop: number;
var childLeft: number;
@@ -735,35 +737,40 @@ export class View extends proxy.ProxyObject implements definition.View {
var childHeight = child.getMeasuredHeight();
var vAlignment: string;
- if (!isNaN(child.height) && child.verticalAlignment === enums.VerticalAlignment.stretch) {
+ if (lp.height >= 0 && child.verticalAlignment === enums.VerticalAlignment.stretch) {
vAlignment = enums.VerticalAlignment.center;
}
else {
vAlignment = child.verticalAlignment;
}
+ let marginTop = lp.topMargin;
+ let marginBottom = lp.bottomMargin;
+ let marginLeft = lp.leftMargin;
+ let marginRight = lp.rightMargin;
+
switch (vAlignment) {
case enums.VerticalAlignment.top:
- childTop = top + child.marginTop * density;
+ childTop = top + marginTop * density;
break;
case enums.VerticalAlignment.center || enums.VerticalAlignment.middle:
- childTop = top + (bottom - top - childHeight + (child.marginTop - child.marginBottom) * density) / 2;
+ childTop = top + (bottom - top - childHeight + (marginTop - marginBottom) * density) / 2;
break;
case enums.VerticalAlignment.bottom:
- childTop = bottom - childHeight - (child.marginBottom * density);
+ childTop = bottom - childHeight - (marginBottom * density);
break;
case enums.VerticalAlignment.stretch:
default:
- childTop = top + child.marginTop * density;
- childHeight = bottom - top - (child.marginTop + child.marginBottom) * density;
+ childTop = top + marginTop * density;
+ childHeight = bottom - top - (marginTop + marginBottom) * density;
break;
}
var hAlignment: string;
- if (!isNaN(child.width) && child.horizontalAlignment === enums.HorizontalAlignment.stretch) {
+ if (lp.width >= 0 && child.horizontalAlignment === enums.HorizontalAlignment.stretch) {
hAlignment = enums.HorizontalAlignment.center;
}
else {
@@ -772,21 +779,21 @@ export class View extends proxy.ProxyObject implements definition.View {
switch (hAlignment) {
case enums.HorizontalAlignment.left:
- childLeft = left + child.marginLeft * density;
+ childLeft = left + marginLeft * density;
break;
case enums.HorizontalAlignment.center:
- childLeft = left + (right - left - childWidth + (child.marginLeft - child.marginRight) * density) / 2;
+ childLeft = left + (right - left - childWidth + (marginLeft - marginRight) * density) / 2;
break;
case enums.HorizontalAlignment.right:
- childLeft = right - childWidth - child.marginRight * density;
+ childLeft = right - childWidth - (marginRight * density);
break;
case enums.HorizontalAlignment.stretch:
default:
- childLeft = left + child.marginLeft * density;
- childWidth = right - left - (child.marginLeft + child.marginRight) * density;
+ childLeft = left + marginLeft * density;
+ childWidth = right - left - (marginLeft + marginRight) * density;
break;
}
@@ -795,7 +802,7 @@ export class View extends proxy.ProxyObject implements definition.View {
childLeft = Math.round(childLeft);
childTop = Math.round(childTop);
- trace.write(parent + " :layoutChild: " + child + " " + childLeft + ", " + childTop + ", " + childRight + ", " + childBottom, trace.categories.Layout);
+ trace.write(child.parent + " :layoutChild: " + child + " " + childLeft + ", " + childTop + ", " + childRight + ", " + childBottom, trace.categories.Layout);
child.layout(childLeft, childTop, childRight, childBottom);
}
@@ -810,19 +817,22 @@ export class View extends proxy.ProxyObject implements definition.View {
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
- trace.write(parent + " :measureChild: " + child + " " + utils.layout.getMode(widthMode) + " " + width + ", " + utils.layout.getMode(heightMode) + " " + height, trace.categories.Layout);
var childWidthMeasureSpec = View.getMeasureSpec(child, width, widthMode, true);
var childHeightMeasureSpec = View.getMeasureSpec(child, height, heightMode, false);
+ trace.write(child.parent + " :measureChild: " + child + " " + utils.layout.measureSpecToString(childWidthMeasureSpec) + ", " + utils.layout.measureSpecToString(childHeightMeasureSpec), trace.categories.Layout);
+
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
measureWidth = child.getMeasuredWidth();
measureHeight = child.getMeasuredHeight();
var density = utils.layout.getDisplayDensity();
+ let lp: CommonLayoutParams = child.style._getValue(style.nativeLayoutParamsProperty);
+
// Convert to pixels.
- measureWidth = Math.round(measureWidth + (child.marginLeft + child.marginRight) * density);
- measureHeight = Math.round(measureHeight + (child.marginTop + child.marginBottom) * density);
+ measureWidth = Math.round(measureWidth + (lp.leftMargin + lp.rightMargin) * density);
+ measureHeight = Math.round(measureHeight + (lp.topMargin + lp.bottomMargin) * density);
}
return { measuredWidth: measureWidth, measuredHeight: measureHeight };
@@ -830,9 +840,11 @@ export class View extends proxy.ProxyObject implements definition.View {
private static getMeasureSpec(view: View, parentLength: number, parentSpecMode: number, horizontal: boolean): number {
+ let lp: CommonLayoutParams = view.style._getValue(style.nativeLayoutParamsProperty);
+
var density = utils.layout.getDisplayDensity();
- var margins = horizontal ? view.marginLeft + view.marginRight : view.marginTop + view.marginBottom;
- margins = Math.floor(margins * density);
+ var margins = horizontal ? lp.leftMargin + lp.rightMargin : lp.topMargin + lp.bottomMargin;
+ margins = Math.round(margins * density);
var resultSize = 0;
var resultMode = 0;
@@ -840,10 +852,10 @@ export class View extends proxy.ProxyObject implements definition.View {
var measureLength = Math.max(0, parentLength - margins);
// Convert to pixels.
- var childLength = Math.floor((horizontal ? view.width : view.height) * density);
+ var childLength = Math.round((horizontal ? lp.width : lp.height) * density);
// We want a specific size... let be it.
- if (!isNaN(childLength)) {
+ if (childLength >= 0) {
if (parentSpecMode !== utils.layout.UNSPECIFIED) {
resultSize = Math.min(parentLength, childLength);
}
diff --git a/ui/core/view.d.ts b/ui/core/view.d.ts
index ede1427e8..71b4e3e0d 100644
--- a/ui/core/view.d.ts
+++ b/ui/core/view.d.ts
@@ -367,24 +367,47 @@ declare module "ui/core/view" {
/**
* Called from layout when this view should assign a size and position to each of its children. Derived classes with children should override this method and call layout on each of their children.
- * @param left Left position, relative to parent
- * @param top Top position, relative to parent
- * @param right Right position, relative to parent
+ * @param left Left position, relative to parent
+ * @param top Top position, relative to parent
+ * @param right Right position, relative to parent
* @param bottom Bottom position, relative to parent
*/
public onLayout(left: number, top: number, right: number, bottom: number): void;
/**
* This method must be called by onMeasure(int, int) to store the measured width and measured height. Failing to do so will trigger an exception at measurement time.
- * @param measuredWidth The measured width of this view. May be a complex bit mask as defined by MEASURED_SIZE_MASK and MEASURED_STATE_TOO_SMALL.
+ * @param measuredWidth The measured width of this view. May be a complex bit mask as defined by MEASURED_SIZE_MASK and MEASURED_STATE_TOO_SMALL.
* @param measuredHeight The measured height of this view. May be a complex bit mask as defined by MEASURED_SIZE_MASK and MEASURED_STATE_TOO_SMALL.
*/
public setMeasuredDimension(measuredWidth: number, measuredHeight: number): void;
+ /**
+ * Called from onLayout when native view position is about to be changed.
+ * @param parent This parameter is not used. You can pass null.
+ * @param left Left position, relative to parent
+ * @param top Top position, relative to parent
+ * @param right Right position, relative to parent
+ * @param bottom Bottom position, relative to parent
+ */
public layoutNativeView(left: number, top: number, right: number, bottom: number): void;
+ /**
+ * Measure a child by taking into account its margins and a given measureSpecs.
+ * @param parent This parameter is not used. You can pass null.
+ * @param child The view to be measured.
+ * @param measuredWidth The measured width that the parent layout specifies for this view.
+ * @param measuredHeight The measured height that the parent layout specifies for this view.
+ */
public static measureChild(parent: View, child: View, widthMeasureSpec: number, heightMeasureSpec: number): { measuredWidth: number; measuredHeight: number };
-
+
+ /**
+ * Layout a child by taking into account its margins, horizontal and vertical alignments and a given bounds.
+ * @param parent This parameter is not used. You can pass null.
+ * @param left Left position, relative to parent
+ * @param top Top position, relative to parent
+ * @param right Right position, relative to parent
+ * @param bottom Bottom position, relative to parent
+ */
public static layoutChild(parent: View, child: View, left: number, top: number, right: number, bottom: number): void;
/**
diff --git a/ui/frame/frame.android.ts b/ui/frame/frame.android.ts
index 78ac97190..e31b97d4a 100644
--- a/ui/frame/frame.android.ts
+++ b/ui/frame/frame.android.ts
@@ -30,9 +30,9 @@ var PageFragmentBody = (android.app.Fragment).extend({
},
onCreateView: function (inflater: android.view.LayoutInflater, container: android.view.ViewGroup, savedInstanceState: android.os.Bundle): android.view.View {
- trace.write(`PageFragmentBody.onCreateView(${inflater}, ${container}, ${savedInstanceState})`, trace.categories.NativeLifecycle);
var entry = this.entry;
var page = entry.resolvedPage;
+ trace.write(`PageFragmentBody.onCreateView(${inflater}, ${page}, ${savedInstanceState})`, trace.categories.NativeLifecycle);
if (savedInstanceState && savedInstanceState.getBoolean(HIDDEN, false)) {
this.super.getFragmentManager().beginTransaction().hide(this).commit();
page._onAttached(this.getActivity());
diff --git a/ui/layouts/absolute-layout/absolute-layout.ios.ts b/ui/layouts/absolute-layout/absolute-layout.ios.ts
index 202b2d72b..33c9b3257 100644
--- a/ui/layouts/absolute-layout/absolute-layout.ios.ts
+++ b/ui/layouts/absolute-layout/absolute-layout.ios.ts
@@ -1,6 +1,7 @@
import utils = require("utils/utils");
import view = require("ui/core/view");
import common = require("./absolute-layout-common");
+import {CommonLayoutParams, nativeLayoutParamsProperty} from "ui/styling/style";
global.moduleMerge(common, exports);
@@ -15,6 +16,7 @@ export class AbsoluteLayout extends common.AbsoluteLayout {
}
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
+ AbsoluteLayout.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
var measureWidth = 0;
@@ -29,14 +31,13 @@ export class AbsoluteLayout extends common.AbsoluteLayout {
var childMeasureSpec = utils.layout.makeMeasureSpec(0, utils.layout.UNSPECIFIED);
var density = utils.layout.getDisplayDensity();
- var count = this.getChildrenCount();
- for (var i = 0; i < count; i++) {
- var child = this.getChildAt(i);
- if (!child || !child._isVisible) {
+ for (let i = 0, count = this.getChildrenCount(); i < count; i++) {
+ let child = this.getChildAt(i);
+ if (!child._isVisible) {
continue;
}
- var childSize = view.View.measureChild(this, child, childMeasureSpec, childMeasureSpec);
+ let childSize = view.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);
}
@@ -57,22 +58,25 @@ export class AbsoluteLayout extends common.AbsoluteLayout {
super.onLayout(left, top, right, bottom);
var density = utils.layout.getDisplayDensity();
- var count = this.getChildrenCount();
- for (var i = 0; i < count; i++) {
- var child = this.getChildAt(i);
- if (!child || !child._isVisible) {
+ for (let i = 0, count = this.getChildrenCount(); i < count; i++) {
+ let child = this.getChildAt(i);
+ if (!child._isVisible) {
continue;
}
- var childWidth = child.getMeasuredWidth();
- var childHeight = child.getMeasuredHeight();
+ let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
- var childLeft = (this.paddingLeft + AbsoluteLayout.getLeft(child)) * density;
- var childTop = (this.paddingTop + AbsoluteLayout.getTop(child)) * density;
- var childRight = childLeft + childWidth + (child.marginLeft + child.marginRight) * density;
- var childBottom = childTop + childHeight + (child.marginTop + child.marginBottom) * density;
+ let childWidth = child.getMeasuredWidth();
+ let childHeight = child.getMeasuredHeight();
+
+ let childLeft = (this.paddingLeft + AbsoluteLayout.getLeft(child)) * density;
+ let childTop = (this.paddingTop + AbsoluteLayout.getTop(child)) * density;
+ let childRight = childLeft + childWidth + (lp.leftMargin + lp.rightMargin) * density;
+ let childBottom = childTop + childHeight + (lp.topMargin + lp.bottomMargin) * density;
view.View.layoutChild(this, child, childLeft, childTop, childRight, childBottom);
}
+
+ AbsoluteLayout.restoreOriginalParams(this);
}
-}
+}
\ No newline at end of file
diff --git a/ui/layouts/dock-layout/dock-layout.ios.ts b/ui/layouts/dock-layout/dock-layout.ios.ts
index ad485e9de..b851b91bd 100644
--- a/ui/layouts/dock-layout/dock-layout.ios.ts
+++ b/ui/layouts/dock-layout/dock-layout.ios.ts
@@ -2,6 +2,7 @@
import view = require("ui/core/view");
import enums = require("ui/enums");
import common = require("./dock-layout-common");
+import {CommonLayoutParams, nativeLayoutParamsProperty} from "ui/styling/style";
global.moduleMerge(common, exports);
@@ -12,6 +13,7 @@ export class DockLayout extends common.DockLayout {
}
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
+ DockLayout.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
var measureWidth = 0;
@@ -32,10 +34,10 @@ export class DockLayout extends common.DockLayout {
var tempWidth: number = 0;
var childWidthMeasureSpec: number;
var childHeightMeasureSpec: number;
- var count = this.getChildrenCount();
- for (var i = 0; i < count; i++) {
- var child = this.getChildAt(i);
- if (!child || !child._isVisible) {
+
+ for (let i = 0, count = this.getChildrenCount(); i < count; i++) {
+ let child = this.getChildAt(i);
+ if (!child._isVisible) {
continue;
}
@@ -49,9 +51,8 @@ export class DockLayout extends common.DockLayout {
childHeightMeasureSpec = utils.layout.makeMeasureSpec(remainingHeight, heightMode === utils.layout.EXACTLY ? utils.layout.AT_MOST : heightMode);
}
- var childSize = view.View.measureChild(this, child, childWidthMeasureSpec, childHeightMeasureSpec);
-
- var dock = DockLayout.getDock(child);
+ let childSize = view.View.measureChild(this, child, childWidthMeasureSpec, childHeightMeasureSpec);
+ let dock = DockLayout.getDock(child);
switch (dock) {
case enums.Dock.top:
@@ -106,16 +107,18 @@ export class DockLayout extends common.DockLayout {
childToStretch = this.getChildAt(count);
}
- for (var i = 0; i < count; i++) {
- var child = this.getChildAt(i);
- if (!child || !child._isVisible) {
+ for (let i = 0; i < count; i++) {
+ let child = this.getChildAt(i);
+ if (!child._isVisible) {
continue;
}
- var childWidth = child.getMeasuredWidth() + (child.marginLeft + child.marginRight) * density;
- var childHeight = child.getMeasuredHeight() + (child.marginTop + child.marginBottom) * density;
+ let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
- var dock = DockLayout.getDock(child);
+ let childWidth = child.getMeasuredWidth() + (lp.leftMargin + lp.rightMargin) * density;
+ let childHeight = child.getMeasuredHeight() + (lp.topMargin + lp.bottomMargin) * density;
+
+ let dock = DockLayout.getDock(child);
switch (dock) {
case enums.Dock.top:
childLeft = x;
@@ -148,11 +151,14 @@ export class DockLayout extends common.DockLayout {
remainingWidth = Math.max(0, remainingWidth - childWidth);
break;
}
+
view.View.layoutChild(this, child, childLeft, childTop, childLeft + childWidth, childTop + childHeight);
}
if (childToStretch) {
view.View.layoutChild(this, childToStretch, x, y, x + remainingWidth, y + remainingHeight);
}
+
+ DockLayout.restoreOriginalParams(this);
}
-}
+}
\ No newline at end of file
diff --git a/ui/layouts/grid-layout/grid-layout.ios.ts b/ui/layouts/grid-layout/grid-layout.ios.ts
index e7cbcd25e..091615591 100644
--- a/ui/layouts/grid-layout/grid-layout.ios.ts
+++ b/ui/layouts/grid-layout/grid-layout.ios.ts
@@ -1,7 +1,8 @@
import utils = require("utils/utils");
-import enums = require("ui/enums");
-import view = require("ui/core/view");
+import {HorizontalAlignment, VerticalAlignment} from "ui/enums";
+import {View} from "ui/core/view";
import common = require("./grid-layout-common");
+import {CommonLayoutParams} from "ui/styling/style";
global.moduleMerge(common, exports);
@@ -26,19 +27,19 @@ export class GridLayout extends common.GridLayout {
this.invalidate();
}
- protected onRowChanged(element: view.View, oldValue: number, newValue: number) {
+ protected onRowChanged(element: View, oldValue: number, newValue: number) {
this.invalidate();
}
- protected onRowSpanChanged(element: view.View, oldValue: number, newValue: number) {
+ protected onRowSpanChanged(element: View, oldValue: number, newValue: number) {
this.invalidate();
}
- protected onColumnChanged(element: view.View, oldValue: number, newValue: number) {
+ protected onColumnChanged(element: View, oldValue: number, newValue: number) {
this.invalidate();
}
- protected onColumnSpanChanged(element: view.View, oldValue: number, newValue: number) {
+ protected onColumnSpanChanged(element: View, oldValue: number, newValue: number) {
this.invalidate();
}
@@ -48,6 +49,7 @@ export class GridLayout extends common.GridLayout {
}
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
+ GridLayout.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
let width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
@@ -109,7 +111,7 @@ export class GridLayout extends common.GridLayout {
let childrenCount = this.getChildrenCount();
for (let i = 0; i < childrenCount; i++) {
let child = this.getChildAt(i);
- if (!child || !child._isVisible) {
+ if (!child._isVisible) {
continue;
}
@@ -131,8 +133,8 @@ export class GridLayout extends common.GridLayout {
measureWidth = Math.max(measureWidth, this.minWidth * density);
measureHeight = Math.max(measureHeight, this.minHeight * density);
- let widthAndState = view.View.resolveSizeAndState(measureWidth, width, widthMode, 0);
- let heightAndState = view.View.resolveSizeAndState(measureHeight, height, heightMode, 0);
+ let widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
+ let heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
this.setMeasuredDimension(widthAndState, heightAndState);
}
@@ -189,9 +191,11 @@ export class GridLayout extends common.GridLayout {
let childBottom = rowOffsets[measureSpec.rowIndex + measureSpec.rowSpan];
// No need to include margins in the width, height
- view.View.layoutChild(this, measureSpec.child, childLeft, childTop, childRight, childBottom);
+ View.layoutChild(this, measureSpec.child, childLeft, childTop, childRight, childBottom);
}
}
+
+ GridLayout.restoreOriginalParams(this);
}
}
@@ -212,7 +216,7 @@ class MeasureSpecs {
public measured: boolean = false;
constructor(
- public child: view.View,
+ public child: View,
public column: common.ItemSpec,
public row: common.ItemSpec,
columnSpan?: number,
@@ -351,11 +355,11 @@ class MeasureHelper {
rowStarValue: number;
get horizontalStretch(): boolean {
- return this.grid.horizontalAlignment === enums.HorizontalAlignment.stretch && !this.infinityWidth;
+ return this.grid.horizontalAlignment === HorizontalAlignment.stretch && !this.infinityWidth;
}
get verticalStretch(): boolean {
- return this.grid.verticalAlignment === enums.VerticalAlignment.stretch && !this.infinityHeight;
+ return this.grid.verticalAlignment === VerticalAlignment.stretch && !this.infinityHeight;
}
get columnsFixed(): boolean {
@@ -630,7 +634,7 @@ class MeasureHelper {
let widthMeasureSpec: number = (measureSpec.autoColumnsCount > 0) ? this.infinity : utils.layout.makeMeasureSpec(measureSpec.pixelWidth, utils.layout.EXACTLY);
let heightMeasureSpec: number = (isFakeMeasure || measureSpec.autoRowsCount > 0) ? this.infinity : utils.layout.makeMeasureSpec(measureSpec.pixelHeight, utils.layout.EXACTLY);
- let childSize = view.View.measureChild(this.grid, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
+ let childSize = View.measureChild(this.grid, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
let columnSpanEnd = measureSpec.columnIndex + measureSpec.columnSpan;
let rowSpanEnd = measureSpec.rowIndex + measureSpec.rowSpan;
@@ -694,7 +698,7 @@ class MeasureHelper {
let widthMeasureSpec = utils.layout.makeMeasureSpec(measureWidth, this.horizontalStretch ? utils.layout.EXACTLY : utils.layout.AT_MOST);
let heightMeasureSpec: number = (measureSpec.autoRowsCount > 0) ? this.infinity : utils.layout.makeMeasureSpec(measureSpec.pixelHeight, utils.layout.EXACTLY);
- let childSize = view.View.measureChild(this.grid, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
+ let childSize = View.measureChild(this.grid, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
this.updateColumnGroupWidth(measureSpec, childSize.measuredWidth);
@@ -739,7 +743,7 @@ class MeasureHelper {
let widthMeasureSpec: number = (measureSpec.autoColumnsCount > 0) ? this.infinity : utils.layout.makeMeasureSpec(measureSpec.pixelWidth, utils.layout.EXACTLY);
let heightMeasureSpec = utils.layout.makeMeasureSpec(measureHeight, this.verticalStretch ? utils.layout.EXACTLY : utils.layout.AT_MOST);
- let childSize = view.View.measureChild(this.grid, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
+ let childSize = View.measureChild(this.grid, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
// Distribute width over auto columns
if (measureSpec.autoColumnsCount > 0) {
@@ -798,7 +802,7 @@ class MeasureHelper {
let widthMeasureSpec = utils.layout.makeMeasureSpec(measureWidth, (measureSpec.starColumnsCount > 0 && !this.horizontalStretch) ? utils.layout.AT_MOST : utils.layout.EXACTLY);
let heightMeasureSpec = utils.layout.makeMeasureSpec(measureHeight, (measureSpec.starRowsCount > 0 && !this.verticalStretch) ? utils.layout.AT_MOST : utils.layout.EXACTLY);
- let childSize = view.View.measureChild(this.grid, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
+ let childSize = View.measureChild(this.grid, measureSpec.child, widthMeasureSpec, heightMeasureSpec);
this.updateColumnGroupWidth(measureSpec, childSize.measuredWidth);
this.updateRowGroupHeight(measureSpec, childSize.measuredHeight);
@@ -830,7 +834,6 @@ class MeasureHelper {
}
private updateColumnGroupWidth(measureSpec: MeasureSpecs, remainingSpace: number): void {
-
// Distribute width over star columns
if (!this.horizontalStretch) {
let columnIndex = measureSpec.columnIndex;
diff --git a/ui/layouts/layout-base.d.ts b/ui/layouts/layout-base.d.ts
index 388bc5390..950ef00a0 100644
--- a/ui/layouts/layout-base.d.ts
+++ b/ui/layouts/layout-base.d.ts
@@ -50,6 +50,20 @@
*/
removeChildren(): 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.
*/
diff --git a/ui/layouts/layout-base.ts b/ui/layouts/layout-base.ts
index f72613418..eda56c429 100644
--- a/ui/layouts/layout-base.ts
+++ b/ui/layouts/layout-base.ts
@@ -2,6 +2,8 @@
import view = require("ui/core/view");
import dependencyObservable = require("ui/core/dependency-observable");
import proxy = require("ui/core/proxy");
+import utils = require("utils/utils");
+import style = require("ui/styling/style");
export class LayoutBase extends view.CustomLayoutView implements definition.LayoutBase, view.AddChildFromBuilder {
@@ -129,4 +131,72 @@ export class LayoutBase extends view.CustomLayoutView implements definition.Layo
var layout = data.object;
layout.onClipToBoundsChanged(data.oldValue, data.newValue);
}
-}
+
+ protected static adjustChildrenLayoutParams(layoutBase: LayoutBase, widthMeasureSpec: number, heightMeasureSpec: number): void {
+ let availableWidth = utils.layout.getMeasureSpecSize(widthMeasureSpec);
+ let widthSpec = utils.layout.getMeasureSpecMode(widthMeasureSpec);
+
+ let availableHeight = utils.layout.getMeasureSpecSize(heightMeasureSpec);
+ let heightSpec = utils.layout.getMeasureSpecMode(heightMeasureSpec);
+
+ for (let i = 0, count = layoutBase.getChildrenCount(); i < count; i++) {
+ let child = layoutBase.getChildAt(i);
+ let lp: style.CommonLayoutParams = child.style._getValue(style.nativeLayoutParamsProperty);
+
+ if (widthSpec !== utils.layout.UNSPECIFIED) {
+ if (lp.widthPercent > 0) {
+ lp.width = Math.round(availableWidth * lp.widthPercent);
+ }
+
+ if (lp.leftMarginPercent > 0) {
+ lp.leftMargin = Math.round(availableWidth * lp.leftMarginPercent);
+ }
+
+ if (lp.rightMarginPercent > 0) {
+ lp.rightMargin = Math.round(availableWidth * lp.rightMarginPercent);
+ }
+ }
+
+ if (heightSpec !== utils.layout.UNSPECIFIED) {
+ if (lp.heightPercent > 0) {
+ lp.height = Math.round(availableHeight * lp.heightPercent);
+ }
+
+ if (lp.topMarginPercent > 0) {
+ lp.topMargin = Math.round(availableHeight * lp.topMarginPercent);
+ }
+
+ if (lp.bottomMarginPercent > 0) {
+ lp.bottomMargin = Math.round(availableHeight * lp.bottomMarginPercent);
+ }
+ }
+ }
+ }
+
+ protected static restoreOriginalParams(layoutBase: LayoutBase): void {
+ for (let i = 0, count = layoutBase.getChildrenCount(); i < count; i++) {
+ let child = layoutBase.getChildAt(i);
+ let lp: style.CommonLayoutParams = child.style._getValue(style.nativeLayoutParamsProperty);
+
+ if (lp.widthPercent > 0) {
+ lp.width = -1;
+ }
+
+ if (lp.heightPercent > 0) {
+ lp.height = -1;
+ }
+ if (lp.leftMarginPercent > 0) {
+ lp.leftMargin = 0;
+ }
+ if (lp.topMarginPercent > 0) {
+ lp.topMargin = 0;
+ }
+ if (lp.rightMarginPercent > 0) {
+ lp.rightMargin = 0;
+ }
+ if (lp.bottomMarginPercent > 0) {
+ lp.bottomMargin = 0;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/layouts/stack-layout/stack-layout.ios.ts b/ui/layouts/stack-layout/stack-layout.ios.ts
index eecc52257..191ac4704 100644
--- a/ui/layouts/stack-layout/stack-layout.ios.ts
+++ b/ui/layouts/stack-layout/stack-layout.ios.ts
@@ -1,7 +1,8 @@
import utils = require("utils/utils");
-import enums = require("ui/enums");
-import view = require("ui/core/view");
+import {Orientation, VerticalAlignment, HorizontalAlignment} from "ui/enums";
+import {View} from "ui/core/view";
import common = require("./stack-layout-common");
+import {CommonLayoutParams, nativeLayoutParamsProperty} from "ui/styling/style";
global.moduleMerge(common, exports);
@@ -10,6 +11,7 @@ export class StackLayout extends common.StackLayout {
private _totalLength = 0;
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
+ StackLayout.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
var density = utils.layout.getDisplayDensity();
@@ -22,12 +24,10 @@ export class StackLayout extends common.StackLayout {
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
- var isVertical = this.orientation === enums.Orientation.vertical;
+ var isVertical = this.orientation === Orientation.vertical;
var verticalPadding = (this.paddingTop + this.paddingBottom) * density;
var horizontalPadding = (this.paddingLeft + this.paddingRight) * density;
- var count = this.getChildrenCount();
-
var measureSpec: number;
var mode = isVertical ? heightMode : widthMode;
@@ -44,32 +44,32 @@ export class StackLayout extends common.StackLayout {
var childMeasureSpec: number;
if (isVertical) {
- var childWidth = (widthMode === utils.layout.UNSPECIFIED) ? 0 : width - horizontalPadding;
+ let childWidth = (widthMode === utils.layout.UNSPECIFIED) ? 0 : width - horizontalPadding;
childWidth = Math.max(0, childWidth);
childMeasureSpec = utils.layout.makeMeasureSpec(childWidth, widthMode)
}
else {
- var childHeight = (heightMode === utils.layout.UNSPECIFIED) ? 0 : height - verticalPadding;
+ let childHeight = (heightMode === utils.layout.UNSPECIFIED) ? 0 : height - verticalPadding;
childHeight = Math.max(0, childHeight);
childMeasureSpec = utils.layout.makeMeasureSpec(childHeight, heightMode)
}
var childSize: { measuredWidth: number; measuredHeight: number };
- for (var i = 0; i < count; i++) {
- var child = this.getChildAt(i);
- if (!child || !child._isVisible) {
+ for (let i = 0, count = this.getChildrenCount(); i < count; i++) {
+ let child = this.getChildAt(i);
+ if (!child._isVisible) {
continue;
}
if (isVertical) {
- childSize = view.View.measureChild(this, child, childMeasureSpec, utils.layout.makeMeasureSpec(remainingLength, measureSpec));
+ childSize = View.measureChild(this, child, childMeasureSpec, utils.layout.makeMeasureSpec(remainingLength, measureSpec));
measureWidth = Math.max(measureWidth, childSize.measuredWidth);
var viewHeight = childSize.measuredHeight;
measureHeight += viewHeight;
remainingLength = Math.max(0, remainingLength - viewHeight);
}
else {
- childSize = view.View.measureChild(this, child, utils.layout.makeMeasureSpec(remainingLength, measureSpec), childMeasureSpec);
+ childSize = View.measureChild(this, child, utils.layout.makeMeasureSpec(remainingLength, measureSpec), childMeasureSpec);
measureHeight = Math.max(measureHeight, childSize.measuredHeight);
var viewWidth = childSize.measuredWidth;
measureWidth += viewWidth;
@@ -85,20 +85,22 @@ export class StackLayout extends common.StackLayout {
this._totalLength = isVertical ? measureHeight : measureWidth;
- var widthAndState = view.View.resolveSizeAndState(measureWidth, width, widthMode, 0);
- var heightAndState = view.View.resolveSizeAndState(measureHeight, height, heightMode, 0);
+ var widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
+ var 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 === enums.Orientation.vertical) {
+ if (this.orientation === 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 {
@@ -114,30 +116,31 @@ export class StackLayout extends common.StackLayout {
var childRight = right - left - paddingRight;
switch (this.verticalAlignment) {
- case enums.VerticalAlignment.center || enums.VerticalAlignment.middle:
+ case VerticalAlignment.center || VerticalAlignment.middle:
childTop = (bottom - top - this._totalLength) / 2 + paddingTop - paddingBottom;
break;
- case enums.VerticalAlignment.bottom:
+ case VerticalAlignment.bottom:
childTop = bottom - top - this._totalLength + paddingTop - paddingBottom;
break;
- case enums.VerticalAlignment.top:
- case enums.VerticalAlignment.stretch:
+ case VerticalAlignment.top:
+ case VerticalAlignment.stretch:
default:
childTop = paddingTop;
break;
}
- var count = this.getChildrenCount();
- for (var i = 0; i < count; i++) {
- var child = this.getChildAt(i);
- if (!child || !child._isVisible) {
+ for (let i = 0, count = this.getChildrenCount(); i < count; i++) {
+ let child = this.getChildAt(i);
+ if (!child._isVisible) {
continue;
}
- var childHeight = child.getMeasuredHeight() + (child.marginTop + child.marginBottom) * density;
- view.View.layoutChild(this, child, childLeft, childTop, childRight, childTop + childHeight);
+ let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
+ let childHeight = child.getMeasuredHeight() + (lp.topMargin + lp.bottomMargin) * density;
+
+ View.layoutChild(this, child, childLeft, childTop, childRight, childTop + childHeight);
childTop += childHeight;
}
}
@@ -155,31 +158,32 @@ export class StackLayout extends common.StackLayout {
var childBottom = bottom - top - paddingBottom;
switch (this.horizontalAlignment) {
- case enums.HorizontalAlignment.center:
+ case HorizontalAlignment.center:
childLeft = (right - left - this._totalLength) / 2 + paddingLeft - paddingRight;
break;
- case enums.HorizontalAlignment.right:
+ case HorizontalAlignment.right:
childLeft = right - left - this._totalLength + paddingLeft - paddingRight;
break;
- case enums.HorizontalAlignment.left:
- case enums.HorizontalAlignment.stretch:
+ case HorizontalAlignment.left:
+ case HorizontalAlignment.stretch:
default:
childLeft = paddingLeft;
break;
}
- var count = this.getChildrenCount();
- for (var i = 0; i < count; i++) {
- var child = this.getChildAt(i);
- if (!child || !child._isVisible) {
+ for (let i = 0, count = this.getChildrenCount(); i < count; i++) {
+ let child = this.getChildAt(i);
+ if (!child._isVisible) {
continue;
}
- var childWidth = child.getMeasuredWidth() + (child.marginLeft + child.marginRight) * density;;
- view.View.layoutChild(this, child, childLeft, childTop, childLeft + childWidth, childBottom);
+ let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
+ let childWidth = child.getMeasuredWidth() + (lp.leftMargin + lp.rightMargin) * density;
+
+ View.layoutChild(this, child, childLeft, childTop, childLeft + childWidth, childBottom);
childLeft += childWidth;
}
}
-}
+}
\ No newline at end of file
diff --git a/ui/layouts/wrap-layout/wrap-layout.ios.ts b/ui/layouts/wrap-layout/wrap-layout.ios.ts
index 4d07734d5..cc3e5983c 100644
--- a/ui/layouts/wrap-layout/wrap-layout.ios.ts
+++ b/ui/layouts/wrap-layout/wrap-layout.ios.ts
@@ -1,13 +1,14 @@
import utils = require("utils/utils");
-import view = require("ui/core/view");
-import enums = require("ui/enums");
import common = require("./wrap-layout-common");
+import {View} from "ui/core/view";
+import {Orientation} from "ui/enums";
+import {CommonLayoutParams, nativeLayoutParamsProperty} from "ui/styling/style";
global.moduleMerge(common, exports);
export class WrapLayout extends common.WrapLayout {
- private _lengths: Array;
+ private _lengths: Array = new Array();
private static getChildMeasureSpec(parentMode: number, parentLength: number, itemLength): number {
if (itemLength > 0) {
@@ -22,6 +23,7 @@ export class WrapLayout extends common.WrapLayout {
}
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
+ WrapLayout.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
var measureWidth = 0;
@@ -33,8 +35,6 @@ export class WrapLayout extends common.WrapLayout {
var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);
- var count = this.getChildrenCount();
-
var density = utils.layout.getDisplayDensity();
var childWidthMeasureSpec: number = WrapLayout.getChildMeasureSpec(widthMode, width, this.itemWidth * density);
var childHeightMeasureSpec: number = WrapLayout.getChildMeasureSpec(heightMode, height, this.itemHeight * density);
@@ -42,18 +42,19 @@ export class WrapLayout extends common.WrapLayout {
var remainingWidth = widthMode === utils.layout.UNSPECIFIED ? Number.MAX_VALUE : width - ((this.paddingLeft + this.paddingRight) * density);
var remainingHeight = heightMode === utils.layout.UNSPECIFIED ? Number.MAX_VALUE : height - ((this.paddingTop + this.paddingBottom) * density);
- this._lengths = [0];
+ this._lengths.length = 0;
+
var rowOrColumn = 0;
var maxLength = 0;
- var i: number = 0;
- var isVertical = this.orientation === enums.Orientation.vertical;
- for (i = 0; i < count; i++) {
- var child = this.getChildAt(i);
- if (!child || !child._isVisible) {
+ var isVertical = this.orientation === Orientation.vertical;
+
+ for (let i = 0, count = this.getChildrenCount(); i < count; i++) {
+ let child = this.getChildAt(i);
+ if (!child._isVisible) {
continue;
}
- var childSize = view.View.measureChild(this, child, childWidthMeasureSpec, childHeightMeasureSpec);
+ var childSize = View.measureChild(this, child, childWidthMeasureSpec, childHeightMeasureSpec);
if (isVertical) {
if (childSize.measuredHeight > remainingHeight) {
rowOrColumn++;
@@ -64,7 +65,6 @@ export class WrapLayout extends common.WrapLayout {
}
else {
remainingHeight -= childSize.measuredHeight;
- this._lengths[rowOrColumn] = Math.max(this._lengths[rowOrColumn], childSize.measuredWidth);
measureHeight += childSize.measuredHeight;
}
}
@@ -78,23 +78,29 @@ export class WrapLayout extends common.WrapLayout {
}
else {
remainingWidth -= childSize.measuredWidth;
- this._lengths[rowOrColumn] = Math.max(this._lengths[rowOrColumn], childSize.measuredHeight);
measureWidth += childSize.measuredWidth;
}
}
+
+ if (this._lengths.length <= rowOrColumn) {
+ this._lengths[rowOrColumn] = isVertical ? childSize.measuredWidth: childSize.measuredHeight;
+ }
+ else {
+ this._lengths[rowOrColumn] = Math.max(this._lengths[rowOrColumn], isVertical ? childSize.measuredWidth : childSize.measuredHeight);
+ }
}
if (isVertical) {
measureHeight = Math.max(maxLength, measureHeight);
- for (i = 0; i < this._lengths.length; i++) {
- measureWidth += this._lengths[i];
- }
+ this._lengths.forEach((value, index, array) => {
+ measureWidth += value;
+ });
}
else {
measureWidth = Math.max(maxLength, measureWidth);
- for (i = 0; i < this._lengths.length; i++) {
- measureHeight += this._lengths[i];
- }
+ this._lengths.forEach((value, index, array) => {
+ measureHeight += value;
+ });
}
measureWidth += (this.paddingLeft + this.paddingRight) * density;
@@ -103,8 +109,8 @@ export class WrapLayout extends common.WrapLayout {
measureWidth = Math.max(measureWidth, this.minWidth * density);
measureHeight = Math.max(measureHeight, this.minHeight * density);
- var widthAndState = view.View.resolveSizeAndState(measureWidth, width, widthMode, 0);
- var heightAndState = view.View.resolveSizeAndState(measureHeight, height, heightMode, 0);
+ var widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
+ var heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
this.setMeasuredDimension(widthAndState, heightAndState);
}
@@ -112,10 +118,9 @@ 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 === enums.Orientation.vertical;
+ var isVertical = this.orientation === Orientation.vertical;
var density = utils.layout.getDisplayDensity();
- var count = this.getChildrenCount();
var childLeft = this.paddingLeft * density;
var childTop = this.paddingTop * density;
@@ -128,21 +133,21 @@ export class WrapLayout extends common.WrapLayout {
}
var rowOrColumn = 0;
- for (var i = 0; i < count; i++) {
- var child = this.getChildAt(i);
- if (!child || !child._isVisible) {
+ for (let i = 0, count = this.getChildrenCount(); i < count; i++) {
+ let child = this.getChildAt(i);
+ if (!child._isVisible) {
continue;
}
// Add margins because layoutChild will sustract them.
// * density converts them to device pixels.
- var childWidth = child.getMeasuredWidth() + (child.marginLeft + child.marginRight) * density;
- var childHeight = child.getMeasuredHeight() + (child.marginTop + child.marginBottom) * density;
+ let lp: CommonLayoutParams = child.style._getValue(nativeLayoutParamsProperty);
- var length = this._lengths[rowOrColumn];
- if (isVertical) {
-
-
+ let childWidth = child.getMeasuredWidth() + (lp.leftMargin + lp.rightMargin) * density;
+ let childHeight = child.getMeasuredHeight() + (lp.topMargin + lp.bottomMargin) * density;
+
+ let length = this._lengths[rowOrColumn];
+ if (isVertical) {
childWidth = length;
childHeight = this.itemHeight > 0 ? this.itemHeight * density : childHeight;
if (childTop + childHeight > childrenLength) {
@@ -177,7 +182,7 @@ export class WrapLayout extends common.WrapLayout {
}
}
- view.View.layoutChild(this, child, childLeft, childTop, childLeft + childWidth, childTop + childHeight);
+ View.layoutChild(this, child, childLeft, childTop, childLeft + childWidth, childTop + childHeight);
if (isVertical) {
// Move next child Top position to bottom.
@@ -188,5 +193,7 @@ export class WrapLayout extends common.WrapLayout {
childLeft += childWidth;
}
}
+
+ WrapLayout.restoreOriginalParams(this);
}
-}
+}
\ No newline at end of file
diff --git a/ui/styling/style.d.ts b/ui/styling/style.d.ts
index d98e5189a..c1bf42371 100644
--- a/ui/styling/style.d.ts
+++ b/ui/styling/style.d.ts
@@ -18,11 +18,19 @@ declare module "ui/styling/style" {
width: number;
height: number;
+ widthPercent: number;
+ heightPercent: number;
+
leftMargin: number;
topMargin: number;
rightMargin: number;
bottomMargin: number;
+ leftMarginPercent: number;
+ topMarginPercent: number;
+ rightMarginPercent: number;
+ bottomMarginPercent: number;
+
horizontalAlignment: string;
verticalAlignment: string;
}
@@ -66,7 +74,7 @@ declare module "ui/styling/style" {
public opacity: number;
public whiteSpace: string;
- new(parentView: View);
+ constructor(parentView: View);
public _beginUpdate();
public _endUpdate();
diff --git a/ui/styling/style.ts b/ui/styling/style.ts
index acd771cb5..c07c7b177 100644
--- a/ui/styling/style.ts
+++ b/ui/styling/style.ts
@@ -13,6 +13,7 @@ import utils = require("utils/utils");
import font = require("ui/styling/font");
import background = require("ui/styling/background");
import platform = require("platform");
+import definition = require("ui/styling/style");
// key is the property id and value is Dictionary;
var _registeredHandlers = Array