-
Notifications
You must be signed in to change notification settings - Fork 0
1.2. 属性系统
MegaUI的属性你可以简单的理解为控件的某些成员变量,比如说按钮中间显示的文字、边框的间距以及颜色、控件是否处于禁用状态等等。
你也许会奇怪,为什么这样一个东西需要单独的介绍。大体上是为了便于提升代码重用性、UI可定制能力以及UI样式与UI内容分离追求,所以用了一些繁琐的实现。
往细节上说:
- 解析器可以无缝适应新的属性,比如说你的自定义控件新增了一些属性。而不必修改解析器代码。
- UI风格高度定制,比如说我希望纯Win32的样式,提供一份Win32的样式即可,而不必对UI整体进行修改。
- 对属性变化做出反应,减少代码编写,比如说,如果处于Pressed,则把背景色改成红色。
OK,下面我们来详细的说明一下属性有那些东西——PropertyInfo。
认真阅读的同学会发现MegaUI参考了微软DirectUI以及WPF的做法。
属性类别 | 描述 |
PI_Local | 控件自身存储的值(意味着并非来自样式表、或者继承、或者默认值)。 |
PI_Specified | 当前控件评估后的值,来自样式表、或者继承、或者默认值。比如说你并未设置Visiable,但是由于Visiable默认值就是true,所以你将得到 true。 |
PI_Computed | 当前控件递归评估后的值。比如说父控件Visiable = false,即使子控件Visiable = true,这也是无济于事的。PI_Computed类别的Visiable将返回false。 |
分类的主要目的是未了让属性更有层次感,避免相互影响。其实Visiable是最能说明问题的。
属性类别 | 描述 |
PF_Cascade | 影响PI_Specified值获取,允许属性从样式表查询。 |
PF_Inherit | 影响PI_Specified值获取,允许属性从父控件继承。 |
PF_ReadOnly | 属性是只读的,无法通过SetValue修改。比如说MouseFocusWithin,很显然值取决于鼠标的位置。 |
一般来说,PI_Specified按如下顺序获取:
- PI_Local值,如果未Unset则继续。
- 尝试从样式表获取(需要属性拥有 PF_Cascade标记),如果未Unset则继续。
- 尝试从父控件继承(需要属性拥有 PF_Inherit标记),如果未Unset则继续。
- 使用默认值
也许你会觉得MegaUI的默认值设计的不合理,居然不支持多态,比如说AccRole属性,为所有的控件均默认为 0。
但是这实际是设计如此,MegaUI设计上故意的剥离了控件自生的特殊性,默认值只是用来保底。
直白的说你应该使用样式表,比如说在样式里把Button控件的AccRole属性设置为AccessibleRole::Button
,而不要指望MegaUI默认的为Button控件的AccRole返回AccessibleRole::Button
。
通过样式表,获得灵活性。
众所周知,某些属性修改后,影响了控件的呈现大小,比如说宽度、高度。而某些属性修改后需要重新绘制,比如说按钮的文案被更改。
局部与绘制往往是低效且耗时的(尤其是后者),所以MegaUI中详细的给属性定义了它的影响范围,尽可能的减少局部与绘制工作。
属性类别 | 描述 |
PG_AffectsDesiredSize | 影响呈现大小。 |
PG_AffectsParentDesiredSize | 影响父控件的呈现大小。 |
PG_AffectsLayout | 影响局部。 |
PG_AffectsParentLayout | 影响父控件的局部。 |
PG_AffectsBounds | 影响位置(x,y)或者大小(宽、高)。 |
PG_AffectsDisplay | 影响显示(言下之意就是需要重新绘制)。 |
如果为0,那么什么也不做,这也是合理的。比如说AccRole属性,它仅仅标识控件的Role,并不影响控件的呈现。
如果发生更改,那么按照fGroups中设置的内容进行重新触发布局或者绘制工作。
温馨提示:属性更改时还将触发依赖更新,比如说在样式表中定义 如果 AccRole ==
AccessibleRole::Button
,那么背景色改成红色。那么AccRole更新后,因为可能更改背景色而触发重新绘制!