Skip to content

1.2. 属性系统

mingkuang edited this page Apr 2, 2023 · 1 revision

背景

MegaUI的属性你可以简单的理解为控件的某些成员变量,比如说按钮中间显示的文字、边框的间距以及颜色、控件是否处于禁用状态等等。

你也许会奇怪,为什么这样一个东西需要单独的介绍。大体上是为了便于提升代码重用性、UI可定制能力以及UI样式与UI内容分离追求,所以用了一些繁琐的实现。

往细节上说:

  1. 解析器可以无缝适应新的属性,比如说你的自定义控件新增了一些属性。而不必修改解析器代码。
  2. UI风格高度定制,比如说我希望纯Win32的样式,提供一份Win32的样式即可,而不必对UI整体进行修改。
  3. 对属性变化做出反应,减少代码编写,比如说,如果处于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是最能说明问题的。

属性支持的Flags(fFlags)

属性类别 描述
PF_Cascade 影响PI_Specified值获取,允许属性从样式表查询。
PF_Inherit 影响PI_Specified值获取,允许属性从父控件继承。
PF_ReadOnly 属性是只读的,无法通过SetValue修改。比如说MouseFocusWithin,很显然值取决于鼠标的位置。

PI_Specified值详细说明

一般来说,PI_Specified按如下顺序获取:

  1. PI_Local值,如果未Unset则继续。
  2. 尝试从样式表获取(需要属性拥有 PF_Cascade标记),如果未Unset则继续。
  3. 尝试从父控件继承(需要属性拥有 PF_Inherit标记),如果未Unset则继续。
  4. 使用默认值

也许你会觉得MegaUI的默认值设计的不合理,居然不支持多态,比如说AccRole属性,为所有的控件均默认为 0。 但是这实际是设计如此,MegaUI设计上故意的剥离了控件自生的特殊性,默认值只是用来保底。 直白的说你应该使用样式表,比如说在样式里把Button控件的AccRole属性设置为AccessibleRole::Button,而不要指望MegaUI默认的为Button控件的AccRole返回AccessibleRole::Button

通过样式表,获得灵活性。

属性的影响范围(fGroups)

众所周知,某些属性修改后,影响了控件的呈现大小,比如说宽度、高度。而某些属性修改后需要重新绘制,比如说按钮的文案被更改。

局部与绘制往往是低效且耗时的(尤其是后者),所以MegaUI中详细的给属性定义了它的影响范围,尽可能的减少局部与绘制工作。

属性类别 描述
PG_AffectsDesiredSize 影响呈现大小。
PG_AffectsParentDesiredSize 影响父控件的呈现大小。
PG_AffectsLayout 影响局部。
PG_AffectsParentLayout 影响父控件的局部。
PG_AffectsBounds 影响位置(x,y)或者大小(宽、高)。
PG_AffectsDisplay 影响显示(言下之意就是需要重新绘制)。

如果为0,那么什么也不做,这也是合理的。比如说AccRole属性,它仅仅标识控件的Role,并不影响控件的呈现。

如果发生更改,那么按照fGroups中设置的内容进行重新触发布局或者绘制工作。

温馨提示:属性更改时还将触发依赖更新,比如说在样式表中定义 如果 AccRole == AccessibleRole::Button,那么背景色改成红色。那么AccRole更新后,因为可能更改背景色而触发重新绘制!