//////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014-present, Egret Technology.
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Egret nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY EGRET AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL EGRET AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////////////
/// false, the object size and position are not affected by its parent container's
* layout.
* This value is different with visible. the object size and position is still affected by its parent
* container's layout when the visible is false.
* @default true
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 指定此组件是否包含在父容器的布局中。若为false,则父级容器在测量和布局阶段都忽略此组件。
* 注意,visible属性与此属性不同,设置visible为false,父级容器仍会对其布局。
*
* @default true
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
includeInLayout: boolean;
/**
* The horizontal distance in pixels from the left edge of the component to the
* anchor target's left edge.
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 距父级容器离左边距离。
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
left: any;
/**
* The horizontal distance in pixels from the right edge of the component to the
* anchor target's right edge.
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 距父级容器右边距离。
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
right: any;
/**
* The vertical distance in pixels from the top edge of the component to the
* anchor target's top edge.
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 距父级容器顶部距离。
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
top: any;
/**
* The vertical distance in pixels from the bottom edge of the component to the
* anchor target's bottom edge.
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 距父级容器底部距离。
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
bottom: any;
/**
* The horizontal distance in pixels from the center of the component to the
* center of the anchor target's content area.
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 在父级容器中距水平中心位置的距离。
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
horizontalCenter: any;
/**
* The vertical distance in pixels from the center of the component to the
* center of the anchor target's content area.
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 在父级容器中距竖直中心位置的距离。
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
verticalCenter: any;
/**
* Specifies the width of a component as a percentage
* of its parent's size. Allowed values are 0-100.
* Setting the width or explicitWidth properties
* resets this property to NaN.
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 相对父级容器宽度的百分比。
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
percentWidth: number;
/**
* Specifies the height of a component as a percentage
* of its parent's size. Allowed values are 0-100.
* Setting the height or explicitHeight properties
* resets this property to NaN.
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 相对父级容器高度的百分比。
*
* @default NaN
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
percentHeight: number;
/**
* Number that specifies the explicit width of the component,
* in pixels, in the component's coordinates.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 外部显式指定的宽度。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
explicitWidth: number;
/**
* Number that specifies the explicit height of the component,
* in pixels, in the component's coordinates.
* @readOnly
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 外部显式指定的高度。
* @readOnly
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
explicitHeight: number;
/**
* The minimum recommended width of the component to be considered
* by the parent during layout. This value is in the
* component's coordinates, in pixels. The default value depends on
* the component's implementation.
* @readOnly
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 组件的最小宽度,此属性设置为大于maxWidth的值时无效。同时影响测量和自动布局的尺寸。
* @readOnly
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
minWidth: number;
/**
* The maximum recommended width of the component to be considered
* by the parent during layout. This value is in the
* component's coordinates, in pixels. The default value of this property is
* set by the component developer.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 组件的最大高度。同时影响测量和自动布局的尺寸。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
maxWidth: number;
/**
* The minimum recommended height of the component to be considered
* by the parent during layout. This value is in the
* component's coordinates, in pixels. The default value depends on
* the component's implementation.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 组件的最小高度,此属性设置为大于maxHeight的值时无效。同时影响测量和自动布局的尺寸。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
minHeight: number;
/**
* The maximum recommended height of the component to be considered
* by the parent during layout. This value is in the
* component's coordinates, in pixels. The default value of this property is
* set by the component developer.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 组件的最大高度,同时影响测量和自动布局的尺寸。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
maxHeight: number;
/**
* Set the result of measuring.
* @param width measured width
* @param height measured height
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 设置测量结果。
* @param width 测量宽度
* @param height 测量高度
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
setMeasuredSize(width: number, height: number): void;
/**
* Marks a component so that its commitProperties()
* method gets called during a later screen update.
commitProperties() method.
* In general, subclassers should
* override the commitProperties() method and not this method.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 由布局逻辑用于通过调用 commitProperties() 方法来验证组件的属性。
* 通常,子类应覆盖 commitProperties() 方法,而不是覆盖此方法。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
validateProperties(): void;
/**
* Marks a component so that its measure()
* method gets called during a later screen update.
*
* Invalidation is a useful mechanism for eliminating duplicate
* work by delaying processing of changes to a component until a
* later screen update.
*
* For example, if you want to change the text and font size,
* it would be wasteful to update the text immediately after you
* change it and then update the size when it gets set.
* It is more efficient to change both properties and then render
* the text with its new size once.
*
* Invalidation methods rarely get called.
* In general, setting a property on a component automatically
* calls the appropriate invalidation method.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 标记提交过需要验证组件尺寸,以便在稍后屏幕更新期间调用该组件的 measure() 方法。
*
* Invalidation 是一个很有用的机制,可将组件更改延迟到稍后屏幕更新时进行处理,从而消除了重复的工作。
*
* 例如,要更改文本和字体大小,如果在更改文本后立即进行更新,然后在设置大小后再更新大小,就有些浪费。
* 更改两个属性后再使用新的大小一次性呈示文本,效率会更高。
*
* 很少调用 Invalidation 方法。通常,在组件上设置属性会自动调用合适的 invalidation 方法。
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
invalidateSize(): void;
/**
* Validates the measured size of the component.
* @param recursive If true, call this method
* on the objects children.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 验证组件的尺寸。
* @param recursive 如果为 true,则调用对象子项的此方法。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
validateSize(recursive?: boolean): void;
/**
* Marks a component so that its updateDisplayList()
* method gets called during a later screen update.
*
* Invalidation is a useful mechanism for eliminating duplicate
* work by delaying processing of changes to a component until a
* later screen update.
*
* For example, if you want to change the width and height,
* it would be wasteful to update the component immediately after you
* change the width and then update again with the new height.
* It is more efficient to change both properties and then render
* the component with its new size once.
*
* Invalidation methods rarely get called.
* In general, setting a property on a component automatically
* calls the appropriate invalidation method.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 标记需要验证显示列表,以便在稍后屏幕更新期间调用该组件的 updateDisplayList() 方法。
*
* Invalidation 是一个很有用的机制,可将组件更改延迟到稍后屏幕更新时进行处理,从而消除了重复的工作。
*
* 例如,要更改宽度和高度,如果在更改宽度后立即更新组件,然后在设置新高度后再次更新组件,就有些浪费。
* 更改两个属性后再使用新的大小一次性呈示组件,效率会更高。
*
* 很少调用 Invalidation 方法。通常,在组件上设置属性会自动调用合适的 invalidation 方法。
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
invalidateDisplayList(): void;
/**
* Validates the position and size of children and draws other
* visuals.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 验证子项的位置和大小,并绘制其他可视内容。
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
validateDisplayList(): void;
/**
* Validate and update the properties and layout of this object
* and redraw it, if necessary.
*
* Processing properties that require substantial computation are normally
* not processed until the script finishes executing.
*
* For example setting the width property is delayed, because it can
* require recalculating the widths of the objects children or its parent.
* Delaying the processing prevents it from being repeated
* multiple times if the script sets the width property more than once.
* This method lets you manually override this behavior.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 验证并更新此对象的属性和布局,如果需要的话重绘对象。
*
* 通常只有当脚本执行完毕后,才会处理要求进行大量计算的处理属性。
*
* 例如,对 width 属性的设置可能会延迟,因为此设置需要重新计算这些对象的子项或父项的宽度。
* 如果脚本多次设置了 width 属性,则延迟处理可防止进行多次处理。此方法允许您手动覆盖此行为。
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
validateNow(): void;
/**
* Sets the layout size of the element.
* This is the size that the element uses to draw on screen.
*
* If the width and/or height parameters are left unspecified (NaN),
* EUI sets the element's layout size to its preferred width and/or preferred height.
*
* Note that calls to the setLayoutBoundSize() method can affect the layout position, so
* call setLayoutBoundPosition() after calling setLayoutBoundSize().
*
* @param layoutWidth The element's layout width.
* @param layoutHeight The element's layout height.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 设置元素的布局大小。这是元素在屏幕上进行绘制时所用的大小。
*
* 如果 width 和/或 height 参数尚未指定 (NaN)),则 EUI 会将该元素的布局大小设置为首选宽度和/或首选高度。
*
* 请注意,调用 setLayoutBoundSize() 方法会影响布局位置,因此请在调用 setLayoutBoundSize()
* 之后再调用 setLayoutBoundPosition()。
*
* @param layoutWidth 元素的布局宽度。
* @param layoutHeight 元素的布局高度。
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
setLayoutBoundsSize(layoutWidth: number, layoutHeight: number): void;
/**
* Sets the coordinates that the element uses to draw on screen.
*
* Note that calls to the setLayoutBoundSize() method can affect the layout position, so
* call setLayoutBoundPosition() after calling setLayoutBoundSize().
*
* @param x The x-coordinate of the top-left corner of the bounding box.
* @param y The y-coordinate of the top-left corner of the bounding box.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 设置元素在屏幕上进行绘制时所用的布局坐标。
*
* 请注意,调用 setLayoutBoundSize() 方法会影响布局位置,因此请在调用 setLayoutBoundSize()
* 之后再调用 setLayoutBoundPosition()。
*
* @param x 边框左上角的 X 坐标。
* @param y 边框左上角的 Y 坐标。
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
setLayoutBoundsPosition(x: number, y: number): void;
/**
* Get the layout bounds that the element uses to draw on screen.
* Commonly used in the updateDisplayList() method in parent container.
* Priority: layout > explicit > measure.
* The result of this method is contains scale and rotation.
*
* @param bounds the instance of egret.Rectangle can set result.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 组件的布局尺寸,常用于父级的updateDisplayList()方法中。
* 按照:布局尺寸>外部显式设置尺寸>测量尺寸 的优先级顺序返回尺寸。
* 注意此方法返回值已经包含scale和rotation。
*
* @param bounds 可以放置结果的egret.Rectangle实例。
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
getLayoutBounds(bounds: egret.Rectangle): void;
/**
* Get the element's preferred bounds。
* Commonly used in the measure() method in parent container.
* Priority: explicit > measure.
* The result of this method is contains scale and rotation.
*
* @param bounds the instance of egret.Rectangle can set result.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 获取组件的首选尺寸,常用于父级的measure()方法中。
* 按照:外部显式设置尺寸>测量尺寸 的优先级顺序返回尺寸。
* 注意此方法返回值已经包含scale和rotation。
*
* @param bounds 可以放置结果的egret.Rectangle实例。
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
getPreferredBounds(bounds: egret.Rectangle): void;
}
}
namespace eui.sys {
/**
* @private
*/
export const enum UIKeys {
left,
right,
top,
bottom,
horizontalCenter,
verticalCenter,
percentWidth,
percentHeight,
explicitWidth,
explicitHeight,
width,
height,
minWidth,
maxWidth,
minHeight,
maxHeight,
measuredWidth,
measuredHeight,
oldPreferWidth,
oldPreferHeight,
oldX,
oldY,
oldWidth,
oldHeight,
invalidatePropertiesFlag,
invalidateSizeFlag,
invalidateDisplayListFlag,
layoutWidthExplicitlySet,
layoutHeightExplicitlySet,
initialized
}
let UIComponentClass = "eui.UIComponent";
function isDeltaIdentity(m: egret.Matrix): boolean {
return (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1);
}
let validator = new sys.Validator();
/**
* @private
* EUI 显示对象基类模板。仅作为 UIComponent 的默认实现,为egret.sys.implemenetUIComponenet()方法提供代码模板。
* 注意:在此类里不允许直接使用super关键字访问父类方法。一律使用this.$super属性访问。
*/
export class UIComponentImpl extends egret.DisplayObject implements eui.UIComponent {
/**
* @private
* 构造函数
*/
public constructor() {
super();
this.initializeUIValues();
}
/**
* @private
* UIComponentImpl 定义的所有变量请不要添加任何初始值,必须统一在此处初始化。
*/
private initializeUIValues(): void {
this.$UIComponent = {
0: NaN, //left
1: NaN, //right
2: NaN, //top
3: NaN, //bottom
4: NaN, //horizontalCenter
5: NaN, //verticalCenter
6: NaN, //percentWidth
7: NaN, //percentHeight
8: NaN, //explicitWidth
9: NaN, //explicitHeight
10: 0, //width
11: 0, //height
12: 0, //minWidth
13: 100000, //maxWidth
14: 0, //minHeight
15: 100000, //maxHeight
16: 0, //measuredWidth
17: 0, //measuredHeight
18: NaN, //oldPreferWidth
19: NaN, //oldPreferHeight
20: 0, //oldX
21: 0, //oldY
22: 0, //oldWidth
23: 0, //oldHeight
24: true, //invalidatePropertiesFlag
25: true, //invalidateSizeFlag
26: true, //invalidateDisplayListFlag
27: false, //layoutWidthExplicitlySet
28: false, //layoutHeightExplicitlySet
29: false, //initialized
};
this.$includeInLayout = true;
//if egret
this.$touchEnabled = true;
//endif*/
}
/**
* @private
* 子类覆盖此方法可以执行一些初始化子项操作。此方法仅在组件第一次添加到舞台时回调一次。
* 请务必调用super.createChildren()以完成父类组件的初始化
*/
protected createChildren(): void {
}
/**
* @private
* 子项创建完成,此方法在createChildren()之后执行。
*/
protected childrenCreated(): void {
}
/**
* @private
* 提交属性,子类在调用完invalidateProperties()方法后,应覆盖此方法以应用属性
*/
protected commitProperties(): void {
let values = this.$UIComponent;
if (values[UIKeys.oldWidth] != values[UIKeys.width] || values[UIKeys.oldHeight] != values[UIKeys.height]) {
this.dispatchEventWith(egret.Event.RESIZE);
values[UIKeys.oldWidth] = values[UIKeys.width];
values[UIKeys.oldHeight] = values[UIKeys.height];
}
if (values[UIKeys.oldX] != this.$getX() || values[UIKeys.oldY] != this.$getY()) {
UIEvent.dispatchUIEvent(this, UIEvent.MOVE);
values[UIKeys.oldX] = this.$getX();
values[UIKeys.oldY] = this.$getY();
}
}
/**
* @private
* 测量组件尺寸
*/
protected measure(): void {
}
/**
* @private
* 更新显示列表
*/
protected updateDisplayList(unscaledWidth: number, unscaledHeight: number): void {
}
$super: any;
$UIComponent: Object;
$includeInLayout: boolean;
/**
* @private
* 指定此组件是否包含在父容器的布局中。若为false,则父级容器在测量和布局阶段都忽略此组件。默认值为true。
* 注意,visible属性与此属性不同,设置visible为false,父级容器仍会对其布局。
*/
public get includeInLayout(): boolean {
return this.$includeInLayout;
}
public set includeInLayout(value: boolean) {
value = !!value;
if (this.$includeInLayout === value)
return;
this.$includeInLayout = true;
this.invalidateParentLayout();
this.$includeInLayout = value;
}
/**
* @private
*
* @param stage
* @param nestLevel
*/
$onAddToStage(stage: egret.Stage, nestLevel: number): void {
this.$super.$onAddToStage.call(this, stage, nestLevel);
this.checkInvalidateFlag();
let values = this.$UIComponent;
if (!values[sys.UIKeys.initialized]) {
values[sys.UIKeys.initialized] = true;
this.createChildren();
this.childrenCreated();
UIEvent.dispatchUIEvent(this, UIEvent.CREATION_COMPLETE);
}
}
/**
* @private
* 检查属性失效标记并应用
*/
private checkInvalidateFlag(event?: Event): void {
let values = this.$UIComponent;
if (values[sys.UIKeys.invalidatePropertiesFlag]) {
validator.invalidateProperties(this);
}
if (values[sys.UIKeys.invalidateSizeFlag]) {
validator.invalidateSize(this);
}
if (values[sys.UIKeys.invalidateDisplayListFlag]) {
validator.invalidateDisplayList(this);
}
}
/**
* @private
* 距父级容器离左边距离
*/
public get left(): any {
return this.$UIComponent[UIKeys.left];
}
public set left(value: any) {
if (!value || typeof value == "number") {
value = +value;
}
else {
value = value.toString().trim();
}
let values = this.$UIComponent;
if (values[UIKeys.left] === value)
return;
values[UIKeys.left] = value;
this.invalidateParentLayout();
}
/**
* @private
* 距父级容器右边距离
*/
public get right(): any {
return this.$UIComponent[UIKeys.right];
}
public set right(value: any) {
if (!value || typeof value == "number") {
value = +value;
}
else {
value = value.toString().trim();
}
let values = this.$UIComponent;
if (values[UIKeys.right] === value)
return;
values[UIKeys.right] = value;
this.invalidateParentLayout();
}
/**
* @private
* 距父级容器顶部距离
*/
public get top(): any {
return this.$UIComponent[UIKeys.top];
}
public set top(value: any) {
if (!value || typeof value == "number") {
value = +value;
}
else {
value = value.toString().trim();
}
let values = this.$UIComponent;
if (values[UIKeys.top] === value)
return;
values[UIKeys.top] = value;
this.invalidateParentLayout();
}
/**
* @private
* 距父级容器底部距离
*/
public get bottom(): any {
return this.$UIComponent[UIKeys.bottom];
}
public set bottom(value: any) {
if (!value || typeof value == "number") {
value = +value;
}
else {
value = value.toString().trim();
}
let values = this.$UIComponent;
if (values[UIKeys.bottom] == value)
return;
values[UIKeys.bottom] = value;
this.invalidateParentLayout();
}
/**
* @private
* 在父级容器中距水平中心位置的距离
*/
public get horizontalCenter(): any {
return this.$UIComponent[UIKeys.horizontalCenter];
}
public set horizontalCenter(value: any) {
if (!value || typeof value == "number") {
value = +value;
}
else {
value = value.toString().trim();
}
let values = this.$UIComponent;
if (values[UIKeys.horizontalCenter] === value)
return;
values[UIKeys.horizontalCenter] = value;
this.invalidateParentLayout();
}
/**
* @private
* 在父级容器中距竖直中心位置的距离
*/
public get verticalCenter(): any {
return this.$UIComponent[UIKeys.verticalCenter];
}
public set verticalCenter(value: any) {
if (!value || typeof value == "number") {
value = +value;
}
else {
value = value.toString().trim();
}
let values = this.$UIComponent;
if (values[UIKeys.verticalCenter] === value)
return;
values[UIKeys.verticalCenter] = value;
this.invalidateParentLayout();
}
/**
* @private
* 相对父级容器宽度的百分比
*/
public get percentWidth(): number {
return this.$UIComponent[UIKeys.percentWidth];
}
public set percentWidth(value: number) {
value = +value;
let values = this.$UIComponent;
if (values[UIKeys.percentWidth] === value)
return;
values[UIKeys.percentWidth] = value;
this.invalidateParentLayout();
}
/**
* @private
* 相对父级容器高度的百分比
*/
public get percentHeight(): number {
return this.$UIComponent[UIKeys.percentHeight];
}
public set percentHeight(value: number) {
value = +value;
let values = this.$UIComponent;
if (values[UIKeys.percentHeight] === value)
return;
values[UIKeys.percentHeight] = value;
this.invalidateParentLayout();
}
/**
* @private
* 外部显式指定的宽度
*/
public get explicitWidth(): number {
return this.$UIComponent[UIKeys.explicitWidth];
}
/**
* @private
* 外部显式指定的高度
*/
public get explicitHeight(): number {
return this.$UIComponent[UIKeys.explicitHeight];
}
/**
* @private
* 组件宽度,默认值为egret.NaN,设置为NaN将使用组件的measure()方法自动计算尺寸
*/
$getWidth(): number {
this.validateSizeNow();
return this.$UIComponent[UIKeys.width];
}
/**
* @private
*
* @param value
*/
$setWidth(value: number): boolean {
value = +value;
let values = this.$UIComponent;
if (value < 0 || values[UIKeys.width] === value && values[UIKeys.explicitWidth] === value)
return false;
values[UIKeys.explicitWidth] = value;
if (isNaN(value))
this.invalidateSize();
this.invalidateProperties();
this.invalidateDisplayList();
this.invalidateParentLayout();
return true;
}
/**
* @private
* 立即验证自身的尺寸。
*/
private validateSizeNow(): void {
this.validateSize(true);
this.updateFinalSize();
}
/**
* @private
* 组件高度,默认值为NaN,设置为NaN将使用组件的measure()方法自动计算尺寸
*/
$getHeight(): number {
this.validateSizeNow();
return this.$UIComponent[UIKeys.height];
}
/**
* @private
*
* @param value
*/
$setHeight(value: number): boolean {
value = +value;
let values = this.$UIComponent;
if (value < 0 || values[UIKeys.height] === value && values[UIKeys.explicitHeight] === value)
return false;
values[UIKeys.explicitHeight] = value;
if (isNaN(value))
this.invalidateSize();
this.invalidateProperties();
this.invalidateDisplayList();
this.invalidateParentLayout();
return true;
}
/**
* @private
* 组件的最小宽度,此属性设置为大于maxWidth的值时无效。同时影响测量和自动布局的尺寸。
*/
public get minWidth(): number {
return this.$UIComponent[UIKeys.minWidth];
}
public set minWidth(value: number) {
value = +value || 0;
let values = this.$UIComponent;
if (value < 0 || values[UIKeys.minWidth] === value) {
return;
}
values[UIKeys.minWidth] = value;
this.invalidateSize();
this.invalidateParentLayout();
}
/**
* @private
* 组件的最大高度。同时影响测量和自动布局的尺寸。
*/
public get maxWidth(): number {
return this.$UIComponent[UIKeys.maxWidth];
}
public set maxWidth(value: number) {
value = +value || 0;
let values = this.$UIComponent;
if (value < 0 || values[UIKeys.maxWidth] === value) {
return;
}
values[UIKeys.maxWidth] = value;
this.invalidateSize();
this.invalidateParentLayout();
}
/**
* @private
* 组件的最小高度,此属性设置为大于maxHeight的值时无效。同时影响测量和自动布局的尺寸。
*/
public get minHeight(): number {
return this.$UIComponent[UIKeys.minHeight];
}
public set minHeight(value: number) {
value = +value || 0;
let values = this.$UIComponent;
if (value < 0 || values[UIKeys.minHeight] === value) {
return;
}
values[UIKeys.minHeight] = value;
this.invalidateSize();
this.invalidateParentLayout();
}
/**
* @private
* 组件的最大高度,同时影响测量和自动布局的尺寸。
*/
public get maxHeight(): number {
return this.$UIComponent[UIKeys.maxHeight];
}
public set maxHeight(value: number) {
value = +value || 0;
let values = this.$UIComponent;
if (value < 0 || values[UIKeys.maxHeight] === value) {
return;
}
values[UIKeys.maxHeight] = value;
this.invalidateSize();
this.invalidateParentLayout();
}
/**
* @private
* 设置测量结果。
* @param width 测量宽度
* @param height 测量高度
*/
public setMeasuredSize(width: number, height: number): void {
let values = this.$UIComponent;
values[UIKeys.measuredWidth] = Math.ceil(+width || 0);
values[UIKeys.measuredHeight] = Math.ceil(+height || 0);
}
/**
* @private
* 设置组件的宽高。此方法不同于直接设置width,height属性,
* 不会影响显式标记尺寸属性
*/
private setActualSize(w: number, h: number): void {
let change = false;
let values = this.$UIComponent;
if (values[UIKeys.width] !== w) {
values[UIKeys.width] = w;
change = true;
}
if (values[UIKeys.height] !== h) {
values[UIKeys.height] = h;
change = true;
}
if (change) {
this.invalidateDisplayList();
this.dispatchEventWith(egret.Event.RESIZE);
}
}
/**
* @private
*/
$invalidateMatrix(): void {
this.$super.$invalidateMatrix.call(this);
this.invalidateParentLayout();
}
/**
* @private
*/
$setMatrix(matrix: egret.Matrix, needUpdateProperties: boolean = true): boolean {
this.$super.$setMatrix.call(this, matrix, needUpdateProperties);
this.invalidateParentLayout();
return true;
}
/**
* @private
*/
$setAnchorOffsetX(value: number): boolean {
this.$super.$setAnchorOffsetX.call(this, value);
this.invalidateParentLayout();
return true;
}
/**
* @private
*/
$setAnchorOffsetY(value: number): boolean {
this.$super.$setAnchorOffsetY.call(this, value);
this.invalidateParentLayout();
return true;
}
/**
* @private
*
* @param value
* @returns
*/
$setX(value: number): boolean {
let change = this.$super.$setX.call(this, value);
if (change) {
this.invalidateParentLayout();
this.invalidateProperties();
}
return change;
}
/**
* @private
*
* @param value
* @returns
*/
$setY(value: number): boolean {
let change = this.$super.$setY.call(this, value);
if (change) {
this.invalidateParentLayout();
this.invalidateProperties();
}
return change;
}
/**
* @private
* 标记属性失效
*/
public invalidateProperties(): void {
let values = this.$UIComponent;
if (!values[sys.UIKeys.invalidatePropertiesFlag]) {
values[sys.UIKeys.invalidatePropertiesFlag] = true;
if (this.$stage)
validator.invalidateProperties(this);
}
}
/**
* @private
* 验证组件的属性
*/
public validateProperties(): void {
let values = this.$UIComponent;
if (values[sys.UIKeys.invalidatePropertiesFlag]) {
this.commitProperties();
values[sys.UIKeys.invalidatePropertiesFlag] = false;
}
}
/**
* @private
* 标记提交过需要验证组件尺寸
*/
public invalidateSize(): void {
let values = this.$UIComponent;
if (!values[sys.UIKeys.invalidateSizeFlag]) {
values[sys.UIKeys.invalidateSizeFlag] = true;
if (this.$stage)
validator.invalidateSize(this);
}
}
/**
* @private
* 验证组件的尺寸
*/
public validateSize(recursive?: boolean): void {
if (recursive) {
let children = this.$children;
if (children) {
let length = children.length;
for (let i = 0; i < length; i++) {
let child = children[i];
if (egret.is(child, UIComponentClass)) {
(