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的大小約束到這麼常見、直接、簡單的功能,都不提供。

相關文章
相關標籤/搜索