GacUI基本概念(二)——排版(1)

这一篇先讲排版的一部分。文章的顺序是按照理解GacUI的顺序来编写的,因此那些难的、不经常使用的东西都会放到最后。显然一个GUI库,用户最关心的就是三个部分:排版、换肤和绑定。可是因为篇幅限制,排版也要分开几篇来写。html

GacUI 排版的基本用法

若是不首先了解GacUI的排版机制的话,直接硬上一般都会遇到,怎么我建立出来的控件的大小是0这样的事情。GacUI不鼓励你hard code大小,因此全部控件都没有尺寸属性。不过我仍是留了一个小后门,当你就是想要这么作的时候,仍是能够作。并且个人设计恰好使得,若是你大规模hard code大小,那用起来就会很苦逼。git

GuiGraphicsComposition

以前咱们已经了解到,GacUI的图形都是由Composition和Element组成的。Composition的基类是 GuiGraphicsComposition 。在这里有几个重要的属性:github

MinSizeLimitation 属性

首先要提出的是,虽然在XML上面能够直接使用这个属性,可是当你使用C++的时候,这个属性是经过 GetMinSizeLimitationSetMinSizeLimitation 来访问的。MinSizeLimitation属性控制的是,这个Composition的大小如何被他的Children所影响。属性的类型是一个枚举类型:算法

enum MinSizeLimitation
{
    NoLimit,
    LimitToElement,
    LimitToElementAndChildren,
};

其中:ui

  • NoLimit:Composition的大小跟他的Children彻底没有关系。.net

  • LimitToElement:Composition的大小仅跟绑定在Composition上面的这个Element有关系。举个例子,若是你的Composition使用了 GuiSolidLabelElement ,那么,Composition最小的大小就是Element里面的文字所决定的大小。固然这个Element里面也有一些设置,譬如说可否换行啊,可否显示省略号等等,这些都会影响最小大小的计算。设计

  • LimitToElementAndChildren:Composition的大小同时受到Element和Children的影响。code

那么Children是如何影响Composition的大小的呢?htm

Margin 和 InternalMargin 属性

使用CSS的朋友们应该都很熟悉,Margin和InternalMargin分别相似于margin和padding的概念。在这里须要特别指出,Children使用的坐标空间是由InternalMargin所决定的,原点恰好是InternalMargin划出来的矩形的左上角。这首先就限制了全部的Children都必须显示在InternalMargin的范围内,超出的部分都会被直接剪裁掉,哪怕他实际上并无超出Composition的范围。继承

而Margin属性则是一个建议,他会告诉上一级的Composition在计算Children的大小的时候,要把Margin考虑进去。

PreferredMinSize 属性

PreferredMinSize属性跟上面的属性能够同时使用。你能够经过给一个值,告诉一个Composition,无论计算出来的最小大小是多少,总之不能小于PreferredMinSize的大小。

GuiBoundsComposition

GuiGraphicsComposition是个抽象类,他是不能直接使用的。若是你须要放一个Composition进你的树里面,一般你会选择 GuiBoundsComposition 或者他的子类。若是一个Composition不继承自GuiBoundsComposition,那么一般意味着,他的尺寸是彻底受到上一级Composition的控制的,譬如Table控制Cell,Stack控制StackItem,Flow控制FlowItem,Document控制DocumentItem这样。

GuiBoundsComposition多出了两个属性,分别是:

AlignmentToParent 属性

AlignmentToParent属性分别强行设置了一个Composition的四个方向,Margin的外面跟上一级Composition的InternalMargin的里面的距离是多少。设置为-1就意味着不规定这个距离。只要你设置了AlignmentToParent,那么这将直接影响到上一级Composition的尺寸的计算。在这里我举个例子:

假设A包含B,而后分别有下面的属性:

A.InternalMargin = {left:1 top:2 right:3 bottom:4}
B.Margin = {left:5 top:5 right:5 bottom:5}
B.PreferredMinSize = {x:100 y:50}
B.AlignmentToParent = {left:-1 top:-1 right:10 bottom:20}

首先咱们能够看出,因为B设置了这一个AlignmentToParent的值,因此不管A的尺寸如何改变,B永远都位于A的左下角,并且B的Margin和A的InternalMargin在右下角的距离分别是10和20。咱们能够很清楚的知道,B的最小尺寸就是100和50,那么A的最小尺寸是多少呢?

首先,A的InternalMargin决定了,A的横向大小不小于left+right=4,纵向大小不小于top+bottom=6;
其次,B的Margin和PreferredMinSize决定了,B占用的A的空间的横向大小不小于left+right+x=110,纵向大小不小于top+bottom+y=60;
再者,B的AlignmentToParent规定了,B的Margin外面和A的InternalMargin里面还有一个10和20的距离;
所以:A的最小尺寸就是4+110+10=124,和6+60+20=86,而后B永远处于A右下角的指定位置。

那么这有什么用呢?若是A是 GuiWindowContainerComposition 属性,而后你放一个B进去,那么当你拖动窗口的大小的时候,你会发现当窗口的客户区小于124和86的时候,窗口就会限制你不能把他拖得更小。事实上,你整颗Composition树的根节点的大小最后会反映到窗口上面去。

Bounds 属性

这是一个喜闻乐见的属性,由于透过这个属性,你就能够强行hard code一个Composition的位置了。你能够经过修改控件的 BoundsComposition 属性的 Bounds 属性,从而强行指定一个控件的位置。然而须要注意的是,Bounds的优先级是最低的,也就是说,若是它的值跟别的属性冲突了(譬如说Size比最小尺寸小,位置跟那些Margin和Alignment有冲突)的话,那么控件的位置和尺寸将不严格按照Bounds的设置摆放。控件会先参考别的属性的值,实在找不到约束了,最后去看Bounds。因此有时候会发现一个控件的位置跟你强行指定的位置不同,就是这个缘由。

我就是不喜欢大家hard code尺寸,哈哈哈哈哈哈。

GuiSharedSize(Root|Item)Composition

除此以外,GacUI还支持不少原生的排版功能。在这些排版功能里面,最有趣的就是SharedSize了。这是什么样的排版呢?假设大家在设计菜单。菜单的文字跟快捷键部分在垂直的方向上是不重叠的。然而他们的父子结构决定了,一个菜单首先按行切割,其次才按列切割。并且你还不能用表格作,由于每个菜单是一个独立的控件,并且菜单里面还能够放别的东西啊。

那如何让一个菜单里面的全部菜单项,会在排版的时候,先互相交换文字和快捷键部分的长度,从而一个显示成这样的菜单:

TEXT1            [CTRL+SHIT+DEL+Z]
A-VERY-LONG-TEXT          [CTRL+Z]

不会被显示成

TEXT1   [CTRL+SHIT+DEL+Z]
A-VERY-LONG-TEXT [CTRL+Z]

呢?这就靠SharedSize了。SharedSize由 GuiSharedSizeRootCompositionGuiSharedSizeItemComposition 组成。其中Item并不须要——并且几乎也不可能——是Root的直接的Children。Root会在排版的时候去寻找(固然算法不可能这么写了这样太慢了)他子树里面的全部Item,而后根据每一个Item设置的Group去分组,最后按照要求统一他们的最小尺寸。

所以在上面的菜单的例子中,咱们能够在整个菜单的外围放一个Root,而每个菜单项控件里面,分别用两个Item放文字跟快捷键,而后设置好分组的名字,文字分为一组,快捷键分为一组。最后要求每个组的宽度都要统一(高度不须要)。最后的结果就是,全部的文字的最小尺寸都由最长的那个决定,全部的快捷键的最小尺寸也都由最长的那个决定,因而排版的结果就至关正确了。

尾声

今天讲的几个属性就是GacUI处理排版的时候的重要内容。固然GacUI不可能只支持这种排版,原生支持的排版功能还有Stack、Table、Flow、SharedSize和Document等。他们的具体内容能够参考 GacUI_Layout 这个demo。细节将在下一篇文章中讲述。除了这五种之外,GacUI还有一些奇形怪状的排版功能,这些基本只在制做控件皮肤的时候用到。

P.S.控制相对位置的功能实在是过重要了,每次在CSS里面搞这些的时候都以为好蛋疼,明明这些功能在GacUI和WPF里面设置出来如此简单,结果CSS连让一个div的大小贝设置成position: relative的child div的大小约束到这么常见、直接、简单的功能,都不提供。

相关文章
相关标签/搜索