Fix order set at runtime, polish unit test app example.

Add alignSelf nad flexWrapBefore in the flexbox examples

Some test fail with quite close calculations. Use eps.

Fix flex grow making last items with flexGrow 0 to shrink due to rounding, happy tslint
This commit is contained in:
Panayot Cankov
2016-10-21 16:11:38 +03:00
parent 3c4199199e
commit ae02bbdff3
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;
}