Merge pull request #2947 from NativeScript/flexbox-ui-tests

Flexbox ui tests
This commit is contained in:
Panayot Cankov
2016-10-24 15:04:52 +03:00
committed by GitHub
7 changed files with 229 additions and 287 deletions

View File

@ -1,11 +1,3 @@
@keyframes select {
0%, 100% {
transform: scale(1, 1);
}
50% {
transform: scale(1.4, 1.4);
}
}
#container>Label {
border-width: 1;
border-color: black;
@ -13,16 +5,18 @@
}
#container>Label[selected="yes"] {
border-color: yellow;
/* animation-name: select;
animation-duration: 0.2s;
animation-fill-mode: forwards;
animation-iteration-count: 1;*/
}
.control {
font-size: 11;
}
.control Button {
padding: 2;
margin: 2;
.control FlexboxLayout {
border-width: 0 0 1 1;
border-color: gray;
}
.control Button {
border-width: 1 1 0 0;
border-color: gray;
padding: 0;
height: 0;
}

View File

@ -1,5 +1,4 @@
import {isAndroid} from "platform";
import * as flexbox from "ui/layouts/flexbox-layout";
import {FlexboxLayout} from "ui/layouts/flexbox-layout";
function set(what: string) {
return function(args) {
@ -15,41 +14,26 @@ export const alignContent = set("alignContent");
let lastSelection = null;
export function select(args) {
console.log("Select: " + args.object);
if (lastSelection) {
lastSelection.selected = "no";
lastSelection.notify({ eventName: "selectedChange", object: lastSelection });
}
lastSelection = args.object;
if (isAndroid) {
let layoutParams = lastSelection.android.getLayoutParams();
console.log("Selection: " + lastSelection + ": " + layoutParams);
console.log(" - margin: " + layoutParams.topMargin + " " + layoutParams.rightMargin + " " + layoutParams.bottomMargin + " " + layoutParams.leftMargin);
if (lastSelection) {
lastSelection.selected = "yes";
lastSelection.notify({ eventName: "selectedChange", object: lastSelection });
}
}
export function order({object}) {
if (!lastSelection) {
return;
}
let value = object.text;
console.log("Set order " + value + " " + lastSelection);
flexbox.FlexboxLayout.setOrder(lastSelection, object.text);
}
let whenSelected = handler => args => lastSelection && handler(args);
let setProperty = setter => value => setter(lastSelection, value);
let intHandler = handler => ({object}) => handler(parseInt(object.text));
let stringHandler = handler => ({object}) => handler(object.text);
let booleanHandler = handler => ({object}) => handler(object.text === "true");
export function flexGrow({object}) {
if (!lastSelection) {
return;
}
let value = object.text;
console.log("Set flexGrow " + value + " " + lastSelection);
flexbox.FlexboxLayout.setFlexGrow(lastSelection, object.text);
}
export const order = whenSelected(intHandler(setProperty(FlexboxLayout.setOrder)));
export const flexGrow = whenSelected(intHandler(setProperty(FlexboxLayout.setFlexGrow)));
export const flexShrink = whenSelected(intHandler(setProperty(FlexboxLayout.setFlexShrink)));
export const alignSelf = whenSelected(stringHandler(setProperty(FlexboxLayout.setAlignSelf)));
export const flexWrapBefore = whenSelected(booleanHandler(setProperty(FlexboxLayout.setFlexWrapBefore)));
export function flexShrink({object}) {
if (!lastSelection) {
return;
}
let value = object.text;
console.log("Set flexShrink " + value + " " + lastSelection);
flexbox.FlexboxLayout.setFlexShrink(lastSelection, object.text);
}
// TODO: Align self

View File

@ -1,119 +1,109 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd">
<GridLayout rows="auto, *" backgroundColor="gray">
<GridLayout class="control" columns="auto, *" rows="30, 30, 30, 30, 30, 25, 30, 30, 30, 30">
<GridLayout rows="auto, *">
<GridLayout class="control" columns="auto, *" rows="30, 30, 30, 30, 30, 25, 15, 15, 15, 30, 30">
<Label row="0" text="FlexDirection" verticalAlignment="center" />
<StackLayout row="0" col="1" orientation="horizontal">
<Button text="row" tap="flexDirection" />
<Button text="row-reverse" tap="flexDirection" />
<Button text="column" tap="flexDirection" />
<Button text="column-reverse" tap="flexDirection" />
</StackLayout>
<FlexboxLayout row="0" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="row" tap="flexDirection" flexGrow="1" automationText="flexDirection-row" />
<Button text="row-reverse" tap="flexDirection" flexGrow="1" automationText="flexDirection-row-reverse" />
<Button text="column" tap="flexDirection" flexGrow="1" automationText="flexDirection-column" />
<Button text="column-reverse" tap="flexDirection" flexGrow="1" automationText="flexDirection-column-reverse" />
</FlexboxLayout>
<Label row="1" text="FlexWrap" verticalAlignment="center" />
<StackLayout row="1" col="1" orientation="horizontal">
<Button text="nowrap" tap="flexWrap" />
<Button text="wrap" tap="flexWrap" />
<Button text="wrap-reverse" tap="flexWrap" />
</StackLayout>
<FlexboxLayout row="1" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="nowrap" tap="flexWrap" flexGrow="1" automationText="flexWrap-nowrap" />
<Button text="wrap" tap="flexWrap" flexGrow="1" automationText="flexWrap-wrap" />
<Button text="wrap-reverse" tap="flexWrap" flexGrow="1" automationText="flexWrap-wrap-reverse" />
</FlexboxLayout>
<!-- TODO: Stretch seems to be default in JavaScript, but not default in Java -->
<Label row="2" text="JustifyContent" verticalAlignment="center" />
<StackLayout row="2" col="1" orientation="horizontal">
<Button text="flex-start" tap="justifyContent" />
<Button text="flex-end" tap="justifyContent" />
<Button text="center" tap="justifyContent" />
<Button text="space-between" tap="justifyContent" />
<Button text="space-around" tap="justifyContent" />
</StackLayout>
<FlexboxLayout row="2" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="flex-start" tap="justifyContent" flexGrow="1" automationText="justifyContent-flex-start" />
<Button text="flex-end" tap="justifyContent" flexGrow="1" automationText="justifyContent-flex-end" />
<Button text="center" tap="justifyContent" flexGrow="1" automationText="justifyContent-center" />
<Button text="space-between" tap="justifyContent" flexGrow="1" automationText="justifyContent-space-between" />
<Button text="space-around" tap="justifyContent" flexGrow="1" automationText="justifyContent-space-around" />
</FlexboxLayout>
<Label row="3" text="AlignItems" verticalAlignment="center" />
<StackLayout row="3" col="1" orientation="horizontal">
<Button text="flex-start" tap="alignItems" />
<Button text="flex-end" tap="alignItems" />
<Button text="center" tap="alignItems" />
<Button text="baseline" tap="alignItems" />
<Button text="stretch" tap="alignItems" />
</StackLayout>
<Label row="3" text="alignItems" verticalAlignment="center" />
<FlexboxLayout row="3" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="flex-start" tap="alignItems" flexGrow="1" automationText="alignItems-flex-start" />
<Button text="flex-end" tap="alignItems" flexGrow="1" automationText="alignItems-flex-end" />
<Button text="center" tap="alignItems" flexGrow="1" automationText="alignItems-center" />
<Button text="baseline" tap="alignItems" flexGrow="1" automationText="alignItems-baseline" />
<Button text="stretch" tap="alignItems" flexGrow="1" automationText="alignItems-stretch" />
</FlexboxLayout>
<Label row="4" text="AlignContent" verticalAlignment="center" />
<StackLayout row="4" col="1" orientation="horizontal">
<Button text="flex-start" tap="alignContent" />
<Button text="flex-end" tap="alignContent" />
<Button text="center" tap="alignContent" />
<Button text="space-between" tap="alignContent" />
<Button text="space-around" tap="alignContent" />
<Button text="stretch" tap="alignContent" />
</StackLayout>
<Label row="4" text="alignContent" verticalAlignment="center" />
<FlexboxLayout row="4" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="flex-start" tap="alignContent" flexGrow="1" automationText="alignItems-flex-start" />
<Button text="flex-end" tap="alignContent" flexGrow="1" automationText="alignItems-flex-end" />
<Button text="center" tap="alignContent" flexGrow="1" automationText="alignItems-center" />
<Button text="space-between" tap="alignContent" flexGrow="1" automationText="alignItems-space-between" />
<Button text="space-around" tap="alignContent" flexGrow="1" automationText="alignItems-space-around" />
<Button text="stretch" tap="alignContent" flexGrow="1" automationText="alignItems-stretch" />
</FlexboxLayout>
<Label row="5" colSpan="2" text="--- selected item properties ---" />
<Label text="order" row="6" />
<StackLayout row="6" col="1" orientation="horizontal">
<Button text="0" tap="order" />
<Button text="1" tap="order" />
<Button text="2" tap="order" />
<Button text="3" tap="order" />
<Button text="4" tap="order" />
</StackLayout>
<FlexboxLayout row="6" col="1" alignContent="stretch">
<Button text="0" tap="order" flexGrow="1" automationText="order-0" />
<Button text="1" tap="order" flexGrow="1" automationText="order-1" />
<Button text="2" tap="order" flexGrow="1" automationText="order-2" />
<Button text="3" tap="order" flexGrow="1" automationText="order-3" />
<Button text="4" tap="order" flexGrow="1" automationText="order-4" />
</FlexboxLayout>
<Label text="flex-grow" row="7" />
<StackLayout row="7" col="1" orientation="horizontal">
<Button text="0" tap="flexGrow" />
<Button text="1" tap="flexGrow" />
<Button text="2" tap="flexGrow" />
<Button text="3" tap="flexGrow" />
<Button text="4" tap="flexGrow" />
</StackLayout>
<Label text="flexGrow" row="7" />
<FlexboxLayout row="7" col="1" alignContent="stretch">
<Button text="0" tap="flexGrow" flexGrow="1" automationText="flexGrow-0" />
<Button text="1" tap="flexGrow" flexGrow="1" automationText="flexGrow-1" />
<Button text="2" tap="flexGrow" flexGrow="1" automationText="flexGrow-2" />
<Button text="3" tap="flexGrow" flexGrow="1" automationText="flexGrow-3" />
<Button text="4" tap="flexGrow" flexGrow="1" automationText="flexGrow-4" />
</FlexboxLayout>
<Label text="flex-shrink" row="8" />
<StackLayout row="8" col="1" orientation="horizontal">
<Button text="0" tap="flexShrink" />
<Button text="1" tap="flexShrink" />
<Button text="2" tap="flexShrink" />
<Button text="3" tap="flexShrink" />
<Button text="4" tap="flexShrink" />
</StackLayout>
<Label text="flexShrink" row="8" />
<FlexboxLayout row="8" col="1" alignContent="stretch">
<Button text="0" tap="flexShrink" flexGrow="1" automationText="flexShrink-0" />
<Button text="1" tap="flexShrink" flexGrow="1" automationText="flexShrink-1" />
<Button text="2" tap="flexShrink" flexGrow="1" automationText="flexShrink-2" />
<Button text="3" tap="flexShrink" flexGrow="1" automationText="flexShrink-3" />
<Button text="4" tap="flexShrink" flexGrow="1" automationText="flexShrink-4" />
</FlexboxLayout>
<!--<Label text="margin" row="9" />
<StackLayout row="9" col="1" orientation="horizontal">
<TextField text="{{margin}}" width="100" />
<Label text="width" />
<TextField text="{{width}}" width="100" />
<Label text="height" />
<TextField text="{{height}}" width="100" />
</StackLayout>-->
<!-- TODO: Align self -->
<Label row="9" text="alignSelf" verticalAlignment="center" />
<FlexboxLayout row="9" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="auto" tap="alignSelf" flexGrow="1" automationText="alignSelf-auto" />
<Button text="flex-start" tap="alignSelf" flexGrow="1" automationText="alignSelf-flex-start" />
<Button text="flex-end" tap="alignSelf" flexGrow="1" automationText="alignSelf-flex-end" />
<Button text="center" tap="alignSelf" flexGrow="1" automationText="alignSelf-center" />
<Button text="baseline" tap="alignSelf" flexGrow="1" automationText="alignSelf-baseline" />
<Button text="stretch" tap="alignSelf" flexGrow="1" automationText="alignSelf-stretch" />
</FlexboxLayout>
<Label row="10" text="flexWrapBefore" verticalAlignment="center" />
<FlexboxLayout row="10" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="true" tap="flexWrapBefore" flexGrow="1" automationText="flexWrapBefore-true" />
<Button text="false" tap="flexWrapBefore" flexGrow="1" automationText="flexWrapBefore-false" />
</FlexboxLayout>
</GridLayout>
<FlexboxLayout id="container" row="1" backgroundColor="white" margin="10">
<!-- TODO: horizontalAlignment and verticalAlignment should be handled somehow by treating the items with proper layout params -->
<Label text="row" backgroundColor="#EEEEEE" margin="20" padding="20" tap="select" />
<Label text="row-reverse" backgroundColor="#DDDDDD" fontSize="8" tap="select" />
<Label text="column" backgroundColor="#CCCCCC" tap="select" />
<Label text="column-reverse" backgroundColor="#BBBBBB" tap="select" />
<Label text="row" backgroundColor="#AAAAAA" tap="select" />
<Label text="row-reverse" backgroundColor="#EEEEEE" fontSize="8" tap="select" />
<Label text="column" backgroundColor="#DDDDDD" tap="select" />
<Label text="column-reverse" backgroundColor="#CCCCCC" tap="select" />
<Label text="row" backgroundColor="#BBBBBB" tap="select" />
<Label text="row-reverse" backgroundColor="#AAAAAA" fontSize="8" tap="select" />
<Label text="column" backgroundColor="#EEEEEE" tap="select" />
<Label text="column-reverse" backgroundColor="#DDDDDD" tap="select" />
<Label text="row" backgroundColor="#CCCCCC" tap="select" />
<Label text="row-reverse" backgroundColor="#BBBBBB" fontSize="8" tap="select" />
<Label text="column" backgroundColor="#AAAAAA" tap="select" />
<Label text="column-reverse" backgroundColor="#EEEEEE" tap="select" />
<Label text="row" backgroundColor="#DDDDDD" tap="select" />
<Label text="row-reverse" backgroundColor="#CCCCCC" fontSize="8" tap="select" />
<Label text="column" backgroundColor="#BBBBBB" tap="select" />
<Label text="column-reverse" backgroundColor="#AAAAAA" tap="select" />
<Label text="row" backgroundColor="#EEEEEE" tap="select" />
<Label text="row-reverse" backgroundColor="#DDDDDD" fontSize="8" tap="select" />
<Label text="column" backgroundColor="#CCCCCC" tap="select" />
<Label text="column-reverse" backgroundColor="#BBBBBB" tap="select" />
<FlexboxLayout id="container" row="1" borderWidth="1" borderColor="black" margin="10">
<Label text="row" tap="select" margin="10" />
<Label text="row-reverse" tap="select" />
<Label text="column" tap="select" />
<Label text="column-reverse" tap="select" />
<Label text="row" tap="select" />
<Label text="row-reverse" tap="select" />
<Label text="column" tap="select" />
<Label text="column-reverse" tap="select" />
<Label text="row" tap="select" />
<Label text="row-reverse" tap="select" />
<Label text="column" tap="select" />
<Label text="column-reverse" tap="select" />
<Label text="row" tap="select" />
</FlexboxLayout>
</GridLayout>
</Page>

View File

@ -500,8 +500,8 @@ export const testJustifyContent_flexEnd_withParentPadding = test(
({root, flexbox, text1, text2, text3}) => {
isLeftOf(text2, text3);
isLeftOf(text1, text2);
equal(width(flexbox) - right(text3), dipToDp(flexbox.paddingRight));
equal(top(text3), dipToDp(flexbox.paddingTop));
closeEnough(width(flexbox) - right(text3), dipToDp(flexbox.paddingRight));
closeEnough(top(text3), dipToDp(flexbox.paddingTop));
}
);
@ -560,8 +560,8 @@ export const testJustifyContent_spaceBetween_withPadding = test(
({root, flexbox, text1, text2, text3}) => {
let space = width(flexbox) - width(text1) - width(text2) - width(text3) - dipToDp(padding) * 2;
space = space / 2;
equal(left(text1), dipToDp(padding));
equal(width(flexbox) - right(text3), dipToDp(padding));
closeEnough(left(text1), dipToDp(padding));
closeEnough(width(flexbox) - right(text3), dipToDp(padding));
check(space - 1 <= left(text2) - right(text1) && left(text2) - right(text1) <= space + 1);
check(space - 1 <= left(text3) - right(text2) && left(text3) - right(text2) <= space + 1);
}
@ -683,8 +683,8 @@ export const testJustifyContent_spaceBetween_flexDirection_column_withPadding =
({root, flexbox, text1, text2, text3}) => {
let space = height(flexbox) - height(text1) - height(text2) - height(text3) - dipToDp(padding) * 2;
space = space / 2;
equal(top(text1), dipToDp(padding));
equal(height(flexbox) - bottom(text3), dipToDp(padding));
closeEnough(top(text1), dipToDp(padding));
closeEnough(height(flexbox) - bottom(text3), dipToDp(padding));
check(space - 1 <= top(text2) - bottom(text1) && top(text2) - bottom(text1) <= space + 1);
check(space - 1 <= top(text3) - bottom(text2) && top(text3) - bottom(text2) <= space + 1);
}
@ -854,7 +854,7 @@ export const testAlignContent_flexEnd_parentPadding = test(
isAbove(text1, text3);
isAbove(text2, text3);
equal(bottom(text3), height(flexbox) - dipToDp(flexbox.paddingBottom));
closeEnough(bottom(text3), height(flexbox) - dipToDp(flexbox.paddingBottom));
}
);
@ -870,7 +870,7 @@ export const testAlignContent_flexEnd_parentPadding_column = test(
isLeftOf(text2, text3);
let { bounds1, bounds2 } = comparableBounds(text3, flexbox);
equal(bounds1.right, bounds2.right - dipToDp(flexbox.paddingRight));
closeEnough(bounds1.right, bounds2.right - dipToDp(flexbox.paddingRight));
}
);
@ -1233,8 +1233,8 @@ export const testAlignItems_flexEnd_parentPadding = test(
({flexbox}) => flexbox.alignItems = AlignItems.FLEX_END,
({root, flexbox, text1, text2, text3}) => {
isRightOf(text2, text1);
equal(bottom(text1), height(flexbox) - dipToDp(flexbox.paddingBottom));
equal(bottom(text2), height(flexbox) - dipToDp(flexbox.paddingBottom));
closeEnough(bottom(text1), height(flexbox) - dipToDp(flexbox.paddingBottom));
closeEnough(bottom(text2), height(flexbox) - dipToDp(flexbox.paddingBottom));
}
);
@ -1246,8 +1246,8 @@ export const testAlignItems_flexEnd_parentPadding_column = test(
},
({root, flexbox, text1, text2, text3}) => {
isBelow(text2, text1);
equal(right(text1), width(flexbox) - dipToDp(flexbox.paddingRight));
equal(right(text2), width(flexbox) - dipToDp(flexbox.paddingRight));
closeEnough(right(text1), width(flexbox) - dipToDp(flexbox.paddingRight));
closeEnough(right(text2), width(flexbox) - dipToDp(flexbox.paddingRight));
}
);
@ -1603,8 +1603,8 @@ export const testMinWidth_initial_width_less_than_minWidth = test(
noop,
({root, flexbox, text1, text2, text3}) => {
let minWidth = 100;
equal(width(text1), dipToDp(100));
equal(width(text2), width(flexbox) - dipToDp(100));
closeEnough(width(text1), dipToDp(100));
closeEnough(width(text2), width(flexbox) - dipToDp(100));
}
);
@ -1621,8 +1621,8 @@ export const testMinWidth_works_as_lower_bound_shrink_to = test(
activity_minwidth_lower_bound_test,
noop,
({root, flexbox, text1, text2, text3, text4}) => {
equal(width(text1), dipToDp(150));
equal(width(flexbox), width(text1) + width(text2) + width(text3) + width(text4));
closeEnough(width(text1), dipToDp(150));
closeEnough(width(flexbox), width(text1) + width(text2) + width(text3) + width(text4));
}
);
@ -1637,8 +1637,8 @@ export const testMinHeight_initial_height_less_than_minHeight = test(
activity_minheight_test,
noop,
({root, flexbox, text1, text2}) => {
equal(height(text1), dipToDp(100));
equal(height(text2), height(flexbox) - dipToDp(100));
closeEnough(height(text1), dipToDp(100));
closeEnough(height(text2), height(flexbox) - dipToDp(100));
}
);
@ -1655,8 +1655,8 @@ export const testMinHeight_works_as_lower_bound_shrink_to = test(
activity_minheight_lower_bound_test,
noop,
({root, flexbox, text1, text2, text3, text4}) => {
equal(height(text1), dipToDp(150));
equal(height(flexbox), height(text1) + height(text2) + height(text3) + height(text4));
closeEnough(height(text1), dipToDp(150));
closeEnough(height(flexbox), height(text1) + height(text2) + height(text3) + height(text4));
}
);
@ -1792,7 +1792,7 @@ export const testWrap_parentPadding_horizontal = test(
({flexbox, text1, text2, text3}) => {
isBelow(text2, text1);
isRightOf(text3, text2);
equal(height(flexbox), dipToDp(flexbox.paddingTop) + dipToDp(flexbox.paddingBottom) + height(text1) + height(text2));
closeEnough(height(flexbox), dipToDp(flexbox.paddingTop) + dipToDp(flexbox.paddingBottom) + height(text1) + height(text2));
}
);
@ -1810,7 +1810,7 @@ export const testWrap_parentPadding_vertical = test(
({flexbox, text1, text2, text3}) => {
isRightOf(text2, text1);
isBelow(text3, text2);
equal(width(flexbox), dipToDp(flexbox.paddingLeft) + dipToDp(flexbox.paddingRight) + width(text1) + width(text2));
closeEnough(width(flexbox), dipToDp(flexbox.paddingLeft) + dipToDp(flexbox.paddingRight) + width(text1) + width(text2));
}
);
@ -1828,7 +1828,7 @@ export const testWrap_childMargin_horizontal = test(
({flexbox, text1, text2, text3}) => {
isBelow(text2, text1);
isRightOf(text3, text2);
equal(height(flexbox), height(text1) + height(text2) + dipToDp(text2.marginTop) + dipToDp(text2.marginBottom));
closeEnough(height(flexbox), height(text1) + height(text2) + dipToDp(text2.marginTop) + dipToDp(text2.marginBottom));
}
);
@ -1891,7 +1891,7 @@ export const testWrap_childMargin_vertical = test(
isRightOf(text2, text1);
isBelow(text3, text2);
// dips anyone?
equal(width(flexbox), width(text1) + width(text2) + dipToDp(text2.marginLeft) + dipToDp(text2.marginRight));
closeEnough(width(flexbox), width(text1) + width(text2) + dipToDp(text2.marginLeft) + dipToDp(text2.marginRight));
}
);

View File

@ -3,7 +3,7 @@ import {View} from "ui/core/view";
import {PropertyMetadata} from "ui/core/proxy";
import {Property, PropertyMetadataSettings, PropertyChangeData} from "ui/core/dependency-observable";
import {registerSpecialProperty} from "ui/builder/special-properties";
import * as platform from "platform";
import {isAndroid} from "platform";
export type Basis = "auto" | number;
@ -12,7 +12,7 @@ const FLEX_GROW_DEFAULT = 0.0;
const FLEX_SHRINK_DEFAULT = 1.0;
// 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;
var affectsLayout = isAndroid ? PropertyMetadataSettings.None : PropertyMetadataSettings.AffectsLayout;
export type FlexDirection = "row" | "row-reverse" | "column" | "column-reverse";
export namespace FlexDirection {
@ -142,18 +142,18 @@ function validateArgs(element: View): View {
*/
export abstract class FlexboxLayoutBase extends LayoutBase {
public static flexDirectionProperty = new Property("flexDirection", "FlexboxLayout", new PropertyMetadata("row", AffectsLayout, undefined, validateFlexDirection, (args: any) => args.object.setNativeFlexDirection(args.newValue)));
public static flexWrapProperty = new Property("flexWrap", "FlexboxLayout", new PropertyMetadata("nowrap", AffectsLayout, undefined, validateFlexWrap, (args: any) => args.object.setNativeFlexWrap(args.newValue)));
public static justifyContentProperty = new Property("justifyContent", "FlexboxLayout", new PropertyMetadata("flex-start", AffectsLayout, undefined, validateJustifyContent, (args: any) => args.object.setNativeJustifyContent(args.newValue)));
public static alignItemsProperty = new Property("alignItems", "FlexboxLayout", new PropertyMetadata("stretch", AffectsLayout, undefined, validateAlignItems, (args: any) => args.object.setNativeAlignItems(args.newValue)));
public static alignContentProperty = new Property("alignContent", "FlexboxLayout", new PropertyMetadata("stretch", AffectsLayout, undefined, validateAlignContent, (args: any) => args.object.setNativeAlignContent(args.newValue)));
public static flexDirectionProperty = new Property("flexDirection", "FlexboxLayout", new PropertyMetadata("row", affectsLayout, undefined, validateFlexDirection, (args: any) => args.object.setNativeFlexDirection(args.newValue)));
public static flexWrapProperty = new Property("flexWrap", "FlexboxLayout", new PropertyMetadata("nowrap", affectsLayout, undefined, validateFlexWrap, (args: any) => args.object.setNativeFlexWrap(args.newValue)));
public static justifyContentProperty = new Property("justifyContent", "FlexboxLayout", new PropertyMetadata("flex-start", affectsLayout, undefined, validateJustifyContent, (args: any) => args.object.setNativeJustifyContent(args.newValue)));
public static alignItemsProperty = new Property("alignItems", "FlexboxLayout", new PropertyMetadata("stretch", affectsLayout, undefined, validateAlignItems, (args: any) => args.object.setNativeAlignItems(args.newValue)));
public static alignContentProperty = new Property("alignContent", "FlexboxLayout", new PropertyMetadata("stretch", affectsLayout, undefined, validateAlignContent, (args: any) => args.object.setNativeAlignContent(args.newValue)));
// TODO: Validation:
public static orderProperty = new Property("order", "FlexboxLayout", new PropertyMetadata(ORDER_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<number>((flexbox, element, oldValue, newValue) => flexbox.onOrderPropertyChanged(element, oldValue, newValue))));
public static flexGrowProperty = new Property("flexGrow", "FlexboxLayout", new PropertyMetadata(FLEX_GROW_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<number>((flexbox, element, oldValue, newValue) => flexbox.onFlexGrowPropertyChanged(element, oldValue, newValue))));
public static flexShrinkProperty = new Property("flexShrink", "FlexboxLayout", new PropertyMetadata(FLEX_SHRINK_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<number>((flexbox, element, oldValue, newValue) => flexbox.onFlexShrinkPropertyChanged(element, oldValue, newValue))));
public static flexWrapBeforeProperty = new Property("flexWrapBefore", "FlexboxLayout", new PropertyMetadata(false, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<boolean>((flexbox, element, oldValue, newValue) => flexbox.onFlexWrapBeforePropertyChanged(element, oldValue, newValue))))
public static alignSelfProperty = new Property("alignSelf", "FlexboxLayout", new PropertyMetadata(AlignSelf.AUTO, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<AlignSelf>((flexbox, element, oldValue, newValue) => flexbox.onAlignSelfPropertyChanged(element, oldValue, newValue))));
public static orderProperty = new Property("order", "FlexboxLayout", new PropertyMetadata(ORDER_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler));
public static flexGrowProperty = new Property("flexGrow", "FlexboxLayout", new PropertyMetadata(FLEX_GROW_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler));
public static flexShrinkProperty = new Property("flexShrink", "FlexboxLayout", new PropertyMetadata(FLEX_SHRINK_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler));
public static flexWrapBeforeProperty = new Property("flexWrapBefore", "FlexboxLayout", new PropertyMetadata(false, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler));
public static alignSelfProperty = new Property("alignSelf", "FlexboxLayout", new PropertyMetadata(AlignSelf.AUTO, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler));
constructor() {
super();
@ -235,24 +235,18 @@ export abstract class FlexboxLayoutBase extends LayoutBase {
protected abstract setNativeAlignItems(alignItems: AlignItems);
protected abstract setNativeAlignContent(alignContent: AlignContent);
protected abstract onOrderPropertyChanged(element: View, oldValue: number, newValue: number): void;
protected abstract onFlexGrowPropertyChanged(element: View, oldValue: number, newValue: number): void;
protected abstract onFlexShrinkPropertyChanged(element: View, oldValue: number, newValue: number): void;
protected abstract onAlignSelfPropertyChanged(element: View, oldValue: AlignSelf, newValue: AlignSelf): void;
protected abstract onFlexWrapBeforePropertyChanged(element: View, oldValue: boolean, newValue: boolean): void;
private static childHandler<V>(handler: (flexbox: FlexboxLayoutBase, element: View, oldValue: V, newValue: V) => void) {
return (data: PropertyChangeData) => {
let element = data.object as View;
private static childHandler<V>(args: PropertyChangeData) {
let element = args.object as View;
if (!(element instanceof View)) {
throw new Error("Element is not View or its descendant.");
}
let flexbox = element.parent;
if (flexbox instanceof FlexboxLayoutBase) {
handler(flexbox, element, data.oldValue, data.newValue);
}
flexbox.invalidate();
}
}
protected abstract invalidate();
}
registerSpecialProperty("order", (instance, propertyValue) => {

View File

@ -8,8 +8,47 @@ import {
AlignSelf,
FlexboxLayoutBase
} from "./flexbox-layout-common";
import {PropertyMetadata} from "ui/core/proxy";
import {PropertyChangeData} from "ui/core/dependency-observable";
import {layout} from "utils/utils";
function setLayoutParamsProperty(view: View, setter: (lp: org.nativescript.widgets.FlexboxLayout.LayoutParams) => void) {
let nativeView: android.view.View = view._nativeView;
if (nativeView) {
var lp = nativeView.getLayoutParams() || new org.nativescript.widgets.FlexboxLayout.LayoutParams();
if (lp instanceof org.nativescript.widgets.FlexboxLayout.LayoutParams) {
setter(lp);
nativeView.setLayoutParams(lp);
}
}
}
function onNativeOrderPropertyChanged({object, newValue}: PropertyChangeData): void {
setLayoutParamsProperty(<View>object, lp => lp.order = newValue);
}
function onNativeFlexGrowPropertyChanged({object, newValue}: PropertyChangeData): void {
setLayoutParamsProperty(<View>object, lp => lp.flexGrow = newValue);
}
function onNativeFlexShrinkPropertyChanged({object, newValue}: PropertyChangeData): void {
setLayoutParamsProperty(<View>object, lp => lp.flexShrink = newValue);
}
function onNativeAlignSelfPropertyChanged({object, newValue}: PropertyChangeData): void {
setLayoutParamsProperty(<View>object, lp => lp.alignSelf = alignSelfMap[newValue]);
}
function onNativeFlexWrapBeforePropertyChanged({object, newValue}: PropertyChangeData): void {
setLayoutParamsProperty(<View>object, lp => lp.wrapBefore = newValue);
}
(<PropertyMetadata>FlexboxLayoutBase.orderProperty.metadata).onSetNativeValue = onNativeOrderPropertyChanged;
(<PropertyMetadata>FlexboxLayoutBase.flexGrowProperty.metadata).onSetNativeValue = onNativeFlexGrowPropertyChanged;
(<PropertyMetadata>FlexboxLayoutBase.flexShrinkProperty.metadata).onSetNativeValue = onNativeFlexShrinkPropertyChanged;
(<PropertyMetadata>FlexboxLayoutBase.alignSelfProperty.metadata).onSetNativeValue = onNativeAlignSelfPropertyChanged;
(<PropertyMetadata>FlexboxLayoutBase.flexWrapBeforeProperty.metadata).onSetNativeValue = onNativeFlexWrapBeforePropertyChanged;
export * from "./flexbox-layout-common";
import FlexboxLayoutWidget = org.nativescript.widgets.FlexboxLayout;
@ -96,35 +135,8 @@ export class FlexboxLayout extends FlexboxLayoutBase {
this.android.setAlignContent(alignContentMap[alignContent]);
}
protected onOrderPropertyChanged(view: View, oldValue: number, newValue: number): void {
this.setLayoutParamsProperty(view, lp => lp.order = newValue);
}
protected onFlexGrowPropertyChanged(view: View, oldValue: number, newValue: number): void {
this.setLayoutParamsProperty(view, lp => lp.flexGrow = newValue);
}
protected onFlexShrinkPropertyChanged(view: View, oldValue: number, newValue: number): void {
this.setLayoutParamsProperty(view, lp => lp.flexShrink = newValue);
}
protected onAlignSelfPropertyChanged(view: View, oldValue: AlignSelf, newValue: AlignSelf): void {
this.setLayoutParamsProperty(view, lp => lp.alignSelf = alignSelfMap[newValue]);
}
protected onFlexWrapBeforePropertyChanged(view: View, oldValue: boolean, newValue: boolean): void {
this.setLayoutParamsProperty(view, lp => lp.wrapBefore = newValue);
}
private setLayoutParamsProperty(view: View, setter: (lp: org.nativescript.widgets.FlexboxLayout.LayoutParams) => void) {
let nativeView: android.view.View = view._nativeView;
if (nativeView) {
var lp = nativeView.getLayoutParams() || new org.nativescript.widgets.FlexboxLayout.LayoutParams();
if (lp instanceof org.nativescript.widgets.FlexboxLayout.LayoutParams) {
setter(lp);
nativeView.setLayoutParams(lp);
}
}
protected invalidate() {
// no operation
}
}

View File

@ -87,8 +87,8 @@ export class FlexboxLayout extends FlexboxLayoutBase {
private _flexLines: FlexLine[] = [];
private _childrenFrozen: boolean[];
public FlexboxLayout() {
//
protected invalidate() {
this.requestLayout();
}
protected setNativeFlexDirection(flexDirection: FlexDirection) {
@ -107,22 +107,6 @@ export class FlexboxLayout extends FlexboxLayoutBase {
// lint happy no-op
}
protected onOrderPropertyChanged(element: View, oldValue: number, newValue: number): void {
// lint happy no-op
}
protected onFlexGrowPropertyChanged(element: View, oldValue: number, newValue: number): void {
// lint happy no-op
}
protected onFlexShrinkPropertyChanged(element: View, oldValue: number, newValue: number): void {
// lint happy no-op
}
protected onAlignSelfPropertyChanged(element: View, oldValue: AlignSelf, newValue: AlignSelf): void {
// lint happy no-op
}
protected onFlexWrapBeforePropertyChanged(element: View, oldValue: boolean, newValue: boolean): void {
// lint happy no-op
}
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
LayoutBase.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
@ -147,13 +131,19 @@ export class FlexboxLayout extends FlexboxLayoutBase {
default:
throw new Error("Invalid value for the flex direction is set: " + this.flexDirection);
}
this._childrenFrozen.length = 0;
}
private _getReorderedChildAt(index: number): View {
let child: View;
if (index < 0 || index >= this._reorderedIndices.length) {
return null;
child = null;
} else {
let reorderedIndex = this._reorderedIndices[index];
child = this.getChildAt(reorderedIndex);
}
return this.getChildAt(this._reorderedIndices[index]);
return child;
}
public addChild(child: View) {
@ -169,8 +159,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
private _createReorderedIndices(viewBeforeAdded: View, indexForViewBeforeAdded: number, paramsForViewBeforeAdded: FlexboxLayout.LayoutParams): number[];
private _createReorderedIndices(): number[];
private _createReorderedIndices(viewBeforeAdded?: View, indexForViewBeforeAdded?: number, paramsForViewBeforeAdded?: FlexboxLayout.LayoutParams)
{
private _createReorderedIndices(viewBeforeAdded?: View, indexForViewBeforeAdded?: number, paramsForViewBeforeAdded?: FlexboxLayout.LayoutParams) {
if (arguments.length === 0) {
let childCount = this.getChildrenCount();
let orders = this._createOrders(childCount);
@ -202,7 +191,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
}
private _sortOrdersIntoReorderedIndices(childCount: number, orders: Order[]): number[] {
orders.sort(/* TODO: Orders... use the comparer? */);
orders.sort((a, b) => a.compareTo(b));
if (!this._orderCache) {
this._orderCache = [];
}
@ -348,11 +337,11 @@ export class FlexboxLayout extends FlexboxLayoutBase {
if (this.flexWrap !== FlexWrap.WRAP_REVERSE) {
let marginTop = flexLine._maxBaseline - FlexboxLayout.getBaseline(child);
marginTop = Math.max(marginTop, lp.topMargin);
largestHeightInLine = Math.max(largestHeightInLine, child.height + marginTop + lp.bottomMargin);
largestHeightInLine = Math.max(largestHeightInLine, child.getActualSize().height + marginTop + lp.bottomMargin);
} else {
let marginBottom = flexLine._maxBaseline - child.getMeasuredHeight() + FlexboxLayout.getBaseline(child);
marginBottom = Math.max(marginBottom, lp.bottomMargin);
largestHeightInLine = Math.max(largestHeightInLine, child.height + lp.topMargin + marginBottom);
largestHeightInLine = Math.max(largestHeightInLine, child.getActualSize().height + lp.topMargin + marginBottom);
}
}
flexLine._crossSize = largestHeightInLine;
@ -535,7 +524,8 @@ export class FlexboxLayout extends FlexboxLayoutBase {
}
let sizeBeforeExpand = flexLine._mainSize;
let needsReexpand = false;
let unitSpace = (maxMainSize - flexLine._mainSize) / flexLine._totalFlexGrow;
let pendingSpace = maxMainSize - flexLine._mainSize;
let unitSpace = pendingSpace / flexLine._totalFlexGrow;
flexLine._mainSize = paddingAlongMainAxis + flexLine._dividerLengthInMainSize;
let accumulatedRoundError = 0;
for (let i = 0; i < flexLine.itemCount; i++) {
@ -549,54 +539,32 @@ export class FlexboxLayout extends FlexboxLayoutBase {
let lp = FlexboxLayout.getLayoutParams(child);
if (this._isMainAxisDirectionHorizontal(flexDirection)) {
if (!this._childrenFrozen[childIndex]) {
let rawCalculatedWidth = child.getMeasuredWidth() + unitSpace * lp.flexGrow;
if (i === flexLine.itemCount - 1) {
rawCalculatedWidth += accumulatedRoundError;
accumulatedRoundError = 0;
}
let newWidth = Math.round(rawCalculatedWidth);
if (newWidth > lp.maxWidth) {
let rawCalculatedWidth = child.getMeasuredWidth() + unitSpace * lp.flexGrow + accumulatedRoundError;
let roundedCalculatedWidth = Math.round(rawCalculatedWidth);
if (roundedCalculatedWidth > lp.maxWidth) {
needsReexpand = true;
newWidth = lp.maxWidth;
roundedCalculatedWidth = lp.maxWidth;
this._childrenFrozen[childIndex] = true;
flexLine._totalFlexGrow -= lp.flexGrow;
} else {
accumulatedRoundError += (rawCalculatedWidth - newWidth);
if (accumulatedRoundError > 1.0) {
newWidth += 1;
accumulatedRoundError -= 1.0;
} else if (accumulatedRoundError < -1.0) {
newWidth -= 1;
accumulatedRoundError += 1.0;
accumulatedRoundError = rawCalculatedWidth - roundedCalculatedWidth;
}
}
child.measure(makeMeasureSpec(newWidth, EXACTLY), makeMeasureSpec(child.getMeasuredHeight(), EXACTLY));
child.measure(makeMeasureSpec(roundedCalculatedWidth, EXACTLY), makeMeasureSpec(child.getMeasuredHeight(), EXACTLY));
}
flexLine._mainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
} else {
if (!this._childrenFrozen[childIndex]) {
let rawCalculatedHeight = child.getMeasuredHeight() + unitSpace * lp.flexGrow;
if (i === flexLine._itemCount - 1) {
rawCalculatedHeight += accumulatedRoundError;
accumulatedRoundError = 0;
}
let newHeight = Math.round(rawCalculatedHeight);
if (newHeight > lp.maxHeight) {
let rawCalculatedHeight = child.getMeasuredHeight() + unitSpace * lp.flexGrow + accumulatedRoundError;
let roundedCalculatedHeight = Math.round(rawCalculatedHeight);
if (roundedCalculatedHeight > lp.maxHeight) {
needsReexpand = true;
newHeight = lp.maxHeight;
roundedCalculatedHeight = lp.maxHeight;
this._childrenFrozen[childIndex] = true;
flexLine._totalFlexGrow -= lp.flexGrow;
} else {
accumulatedRoundError += (rawCalculatedHeight - newHeight);
if (accumulatedRoundError > 1.0) {
newHeight += 1;
accumulatedRoundError -= 1.0;
} else if (accumulatedRoundError < -1.0) {
newHeight -= 1;
accumulatedRoundError += 1.0;
accumulatedRoundError = rawCalculatedHeight - roundedCalculatedHeight;
}
}
child.measure(makeMeasureSpec(child.getMeasuredWidth(), EXACTLY), makeMeasureSpec(newHeight, EXACTLY));
child.measure(makeMeasureSpec(child.getMeasuredWidth(), EXACTLY), makeMeasureSpec(roundedCalculatedHeight, EXACTLY));
}
flexLine._mainSize += child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
}