mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 11:42:04 +08:00
Implements: Proxy layout properties for the ProxyViewContainer (#8150)
* feat(ProxyViewContainer): proxy layout properties to children * update import path * fix(ProxyViewContainer): Layout properties not applied to new children * test(ProxyViewContainer): Add test for layout properties * chore: fix tslint errors
This commit is contained in:

committed by
Alexander Vakrilov

parent
3199a392b4
commit
2bb7ad9d01
@ -1,5 +1,8 @@
|
|||||||
import { ProxyViewContainer as ProxyViewContainerDefinition } from ".";
|
import { ProxyViewContainer as ProxyViewContainerDefinition } from ".";
|
||||||
import { LayoutBase, View, traceEnabled, traceWrite, traceCategories, CSSType } from "../layouts/layout-base";
|
import { LayoutBase, View, traceEnabled, traceWrite, traceCategories, CSSType } from "../layouts/layout-base";
|
||||||
|
import { Property } from "../core/properties/properties";
|
||||||
|
import { messageType } from "../../trace/trace";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Proxy view container that adds all its native children directly to the parent.
|
* Proxy view container that adds all its native children directly to the parent.
|
||||||
* To be used as a logical grouping container of views.
|
* To be used as a logical grouping container of views.
|
||||||
@ -11,6 +14,7 @@ import { LayoutBase, View, traceEnabled, traceWrite, traceCategories, CSSType }
|
|||||||
// * Proxy (with children) is removed form the DOM. In _removeViewFromNativeVisualTree recursively when the proxy is removed from its parent.
|
// * Proxy (with children) is removed form the DOM. In _removeViewFromNativeVisualTree recursively when the proxy is removed from its parent.
|
||||||
@CSSType("ProxyViewContainer")
|
@CSSType("ProxyViewContainer")
|
||||||
export class ProxyViewContainer extends LayoutBase implements ProxyViewContainerDefinition {
|
export class ProxyViewContainer extends LayoutBase implements ProxyViewContainerDefinition {
|
||||||
|
private proxiedLayoutProperties = new Set<string>();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -62,10 +66,19 @@ export class ProxyViewContainer extends LayoutBase implements ProxyViewContainer
|
|||||||
|
|
||||||
public _addViewToNativeVisualTree(child: View, atIndex?: number): boolean {
|
public _addViewToNativeVisualTree(child: View, atIndex?: number): boolean {
|
||||||
if (traceEnabled()) {
|
if (traceEnabled()) {
|
||||||
traceWrite("ViewContainer._addViewToNativeVisualTree for a child " + child + " ViewContainer.parent: " + this.parent, traceCategories.ViewHierarchy);
|
traceWrite("ProxyViewContainer._addViewToNativeVisualTree for a child " + child + " ViewContainer.parent: " + this.parent, traceCategories.ViewHierarchy);
|
||||||
}
|
}
|
||||||
super._addViewToNativeVisualTree(child);
|
super._addViewToNativeVisualTree(child);
|
||||||
|
|
||||||
|
layoutProperties.forEach((propName) => {
|
||||||
|
const proxyPropName = makeProxyPropName(propName);
|
||||||
|
child[proxyPropName] = child[propName];
|
||||||
|
|
||||||
|
if (this.proxiedLayoutProperties.has(propName)) {
|
||||||
|
this._applyLayoutPropertyToChild(child, propName, this[propName]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const parent = this.parent;
|
const parent = this.parent;
|
||||||
if (parent instanceof View) {
|
if (parent instanceof View) {
|
||||||
let baseIndex = 0;
|
let baseIndex = 0;
|
||||||
@ -147,4 +160,90 @@ export class ProxyViewContainer extends LayoutBase implements ProxyViewContainer
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layout property changed, proxy the new value to the child view(s)
|
||||||
|
*/
|
||||||
|
public _changedLayoutProperty(propName: string, value: string) {
|
||||||
|
const numChildren = this._getNativeViewsCount();
|
||||||
|
if (numChildren > 1) {
|
||||||
|
traceWrite("ProxyViewContainer._changeLayoutProperty - you're setting '" + propName + "' for " + this + " with more than one child. Probably this is not what you want, consider wrapping it in a StackLayout ", traceCategories.ViewHierarchy, messageType.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.eachLayoutChild((child) => {
|
||||||
|
this._applyLayoutPropertyToChild(child, propName, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.proxiedLayoutProperties.add(propName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the layout property to the child view.
|
||||||
|
*/
|
||||||
|
private _applyLayoutPropertyToChild(child: View, propName: string, value: any) {
|
||||||
|
const proxyPropName = makeProxyPropName(propName);
|
||||||
|
if (proxyPropName in child) {
|
||||||
|
if (child[propName] !== child[proxyPropName]) {
|
||||||
|
// Value was set directly on the child view, don't override.
|
||||||
|
if (traceEnabled()) {
|
||||||
|
traceWrite("ProxyViewContainer._applyLayoutPropertyToChild child " + child + " has its own value [" + child[propName] + "] for [" + propName + "]", traceCategories.ViewHierarchy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
child[propName] = value;
|
||||||
|
child[proxyPropName] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layout propeties to be proxyed to the child views
|
||||||
|
const layoutProperties = [
|
||||||
|
// AbsoluteLayout
|
||||||
|
"left",
|
||||||
|
"top",
|
||||||
|
|
||||||
|
// DockLayout
|
||||||
|
"dock",
|
||||||
|
|
||||||
|
// FlexLayout
|
||||||
|
"flexDirection",
|
||||||
|
"flexWrap",
|
||||||
|
"justifyContent",
|
||||||
|
"alignItems",
|
||||||
|
"alignContent",
|
||||||
|
"order",
|
||||||
|
"flexGrow",
|
||||||
|
"flexShrink",
|
||||||
|
"flexWrapBefore",
|
||||||
|
"alignSelf",
|
||||||
|
"flexFlow",
|
||||||
|
"flex",
|
||||||
|
|
||||||
|
// GridLayout
|
||||||
|
"column",
|
||||||
|
"columnSpan",
|
||||||
|
"col",
|
||||||
|
"colSpan",
|
||||||
|
"row",
|
||||||
|
"rowSpan",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Override the inherited layout properties
|
||||||
|
for (const name of layoutProperties) {
|
||||||
|
const proxyProperty = new Property<ProxyViewContainer, string>({
|
||||||
|
name,
|
||||||
|
valueChanged(target, oldValue, value) {
|
||||||
|
target._changedLayoutProperty(name, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
proxyProperty.register(ProxyViewContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeProxyPropName(propName) {
|
||||||
|
return `_proxy:${propName}`;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,35 @@ export function test_children_immediately_registered_in_parent_grid_layout() {
|
|||||||
helper.buildUIAndRunTest(outer, testAction);
|
helper.buildUIAndRunTest(outer, testAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function test_proxy_layout_properties() {
|
||||||
|
const outer = new GridLayout();
|
||||||
|
const proxy = new ProxyViewContainer();
|
||||||
|
|
||||||
|
function testAction(views: Array<View>) {
|
||||||
|
outer.addChild(proxy);
|
||||||
|
|
||||||
|
const btn = createBtn("1");
|
||||||
|
proxy.addChild(btn);
|
||||||
|
|
||||||
|
proxy.row = 1;
|
||||||
|
TKUnit.assertEqual(proxy.row, btn.row, "Proxy row value to existing child");
|
||||||
|
|
||||||
|
const btn2 = createBtn("2");
|
||||||
|
proxy.addChild(btn2);
|
||||||
|
TKUnit.assertEqual(proxy.row, btn2.row, "Proxy row value to new child");
|
||||||
|
|
||||||
|
proxy.removeChild(btn2);
|
||||||
|
|
||||||
|
btn.row = 0;
|
||||||
|
TKUnit.assertNotEqual(proxy.row, btn.row, "Child value changed");
|
||||||
|
|
||||||
|
proxy.row = 1;
|
||||||
|
TKUnit.assertNotEqual(proxy.row, btn.row, "Changed child value not overridden");
|
||||||
|
}
|
||||||
|
|
||||||
|
helper.buildUIAndRunTest(outer, testAction);
|
||||||
|
}
|
||||||
|
|
||||||
export function test_children_registered_in_parent_grid_layout_on_attach() {
|
export function test_children_registered_in_parent_grid_layout_on_attach() {
|
||||||
const outer = new GridLayout();
|
const outer = new GridLayout();
|
||||||
const proxy = new ProxyViewContainer();
|
const proxy = new ProxyViewContainer();
|
||||||
|
Reference in New Issue
Block a user