Skip to content

Commit

Permalink
update doc
Browse files Browse the repository at this point in the history
  • Loading branch information
dustpg committed Jul 3, 2020
1 parent 530da50 commit 01359aa
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 22 deletions.
22 changes: 12 additions & 10 deletions doc/blog/layout-size.md → doc/blog/box-layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

以width作为例子

类型 | 下限 | 建议 | 上限
类型| 下限 | 建议 | 上限
----|--------------|--------------|----------
CSS | min-width | width| max-width
LUI | limited-width| fitting-width| max-width
Expand All @@ -12,24 +12,24 @@ CSS的属性会覆写LUI属性对应值,并且处于高优先级。即:
- 如果指定了CSS属性,那么写入对应的LUI属性,再标记处于CSS状态
- 如果没有指定CSS属性,那么LUI属性会按照相应的规则处理
- 可以通过`style`或者直接的属性进行CSS属性设置
- (例: 可以使用xml属性`minwidth`或者css属性`min-width`设置)

```cpp
case BKDR_MINWIDTH:
// minwidth : width属性下限
m_oStyle.limited.width = value.ToFloat();
reinterpret_cast<uint8_t&>(m_oStyle.overflow_xex) |= uint8_t(4 << 2);
/* xxx */
break;
```



一个最简单的例子就是图像`<image>`,建议宽度就是使用图片的宽度,下限宽度可以考虑`0`。但是需要设置`flex`为有效值, 否则布局器依然会按照图片尺寸布局.

复杂点的例子就是箱型布局`<box>`。LongUI中,使用对应滚动条(这里就是水平滚动条)的`<box>`下限宽度会调整到`0`,建议宽度依然是有效子控件建议宽度(以及 `margin` 什么的,具体来说是 CSS 属性`box-sizing`控制的,XUL默认是`box-sizing: border-box`, LongUI中目前不支持动态切换`box-sizing`)累加.

而一旦使用CSS值,则以设置值为准。

正常控件大小应该介于建议值与最大值之间,特殊情况会处于最小值与建议值之间。而这种特殊情况`<box>`处理方式有点违背常理——`flex`越大的值反而最小,可以理解为以建议值作为起点`flex`作为伸缩参数,越大的伸得越大,缩得也越大
正常控件大小应该介于建议值与最大值之间,特殊情况会处于最小值与建议值之间。而这种特殊情况`<box>`处理方式有点违背常理——`flex`越大的值反而最小,可以理解为**以建议值作为起点**`flex`作为伸缩参数,越大的伸得越大,缩得也越小


# 布局算法
Expand All @@ -42,28 +42,30 @@ LongUI中`<box>`布局算法如下, 为了方便说明先定义一些东西:

具体算法,以`<hbox>`为栗子:
1. 确定有效内容区大小,自身建议宽度等预备数据
2. 先将有效布局子控件中`flex`(`f`)累加起来作为`F``F`自然最小为`0`
2. 先将有效布局子控件中`flex`(作为`f`)累加起来作为`F``F`自然最小为`0`
3. 有效内容区宽度 减去 建议宽度 作为`S`, 注意`S`可能为负数
4. 遍历每个有效布局子控件,将控件临时宽度设置为建议宽度
5.`U = S / F`. 当`F``0`时, 结束计算. (注: 如果`F`实现为浮点数时候注意浮点误差)
6. 遍历每个有效布局子控件
7. 将控件临时宽度 加上 `f * U`, 注意需要将宽度钳制到`min-width max-width`之间
7. 将控件临时宽度 加上 `f * U`, 注意需要将宽度钳制到上下限值之间
8.`S`减去 实际变化量
9. `S`有变化,并且当宽度被钳制时, 让`F`减去`f`
10. 如果`F`没有变化,也结束计算,否则回到步骤5。


算法复杂度:
- 极大概率: O(N)
- 只需要遍历`0~2`
- 理论最差: O(N^2)
- 精心构造的数据可以让每次遍历都有剩余,直到第`N`次,检测到不会改变后退出循环

最后确定的临时宽度就是控件的最终宽度而控件的另一维度,即高度,由其他属性控制。与主维度宽度相比就简单多了。
最后确定的临时宽度就是控件的最终宽度而控件的另一维度,即高度,由其他属性控制。与主维度宽度相比就简单多了。

- 如果可以缩放,在min-height 与 max-height之间匹配合适的高度
- 如果可以缩放,在上下限之间匹配合适的高度
- 否则就是`height`
- 可以缩放的条件是`align: stretcht`
- 合适的高度是指内容高度与**实际**最低高度的极大值
- 之所以是实际,XUL中如果`<box>`使用`style="overflow:auto"`后会改变(LUI中)自身下限值的设置规则——因为可以滚动了,所以下限值变成0。
- 之所以是实际,XUL中如果`<box>`使用滚动条(例如: `style="overflow:auto"`)后会改变(自身下限值的设置规则——因为可以滚动了,所以下限值变成0。

# 深入了解
这个部分是通过栗子详细了解`<box>`布局,所以先给代码,再给问题,最后给解释。
Expand All @@ -75,7 +77,7 @@ LongUI中`<box>`布局算法如下, 为了方便说明先定义一些东西:
<label crop="end" value="AAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBB"/>
</hbox>
```
然后吧 `hbox` 换成 `vbox`
然后把 `hbox` 换成 `vbox`
```xml
<vbox flex="1">
<label crop="end" value="AAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBB"/>
Expand Down
16 changes: 9 additions & 7 deletions doc/blog/thread-safe.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
### 线程安全
# 线程安全

LongUI默认(应该)拥有两条线程: UI线程与渲染线程.

Expand All @@ -20,7 +20,8 @@ void one_frame() {

一般情况如果修改基本数据, 就应该添加数据锁; 修改渲染数据就需要渲染锁. 但是LongUI强烈建议渲染数据应该被隐藏起来: **```update```时检测渲染数据的副本被修改了, 然后向渲染器提交新的渲染数据**. 这时候只需要无脑地使用数据锁而不用担心渲染锁(除非必须及时修改渲染数据, 窗口级一般会需要)

### 时间胶囊 Time Capsule
# 时间胶囊

时间胶囊是LongUI异步处理的一种办法: **将函数包装放在未来一段时间每帧连续调用直到时间耗尽**. 当然, 这个类一开始设计的时候是设计成放在未来某时刻调用一次, 所以取名为时间胶囊. 后来发现有些东西需要连续调用干脆就合并在里面了, 也****得换名字.

时间胶囊总是在渲染时, **在UI线程**进行调用(默认双线程情况):
Expand Down Expand Up @@ -80,7 +81,9 @@ class UILabel {

换句话说时间胶囊中的函数应该是**无锁编程**, 安心地在时间胶囊中调用 ```UILabel::SetText``` 而不用加锁!

### 利用CUIBlockingGuiOpAutoUnlocker调用堵塞函数
# 线程死锁

# 调用堵塞函数

LongUI仅仅是一个简单的GUI库, 不是一套完整的解决方案, 不可能像Qt那样封装全部操作系统的函数. 有时可能需要调用一些操作系统GUI函数: 最简单的比如``` MessageBox ```, 稍微复杂点的 ``` GetOpenFileName ``` , 这些都是堵塞型的.

Expand Down Expand Up @@ -117,7 +120,7 @@ void call() {
}
```

### 利用 UIControl::ControlMakingBegin/End 创建大量控件
# 创建大量控件


为了保证正确性, 请在创建大量控件时使用``` UIControl::ControlMakingBegin `````` UIControl::ControlMakingEnd ```包裹创建过程, 比如``` UIControl::SetXul ```是这样实现的:
Expand All @@ -132,7 +135,7 @@ void LongUI::UIControl::SetXul(const char* xul) noexcept {
这样做是为了避免控件创建到一半就被渲染线程调用 —— 导致部分控件上一帧创建, 部分控件下一帧创建. 如果有其他更好地方法处理线程问题, 这两条函数将会删除(一个空函数壳子), 所以不建议直接调用```DataLock``` (查看LUI_BETA_CTOR_LOCKER)
### impl::ctor_lock 与 impl::ctor_unlock
## impl::ctor_lock 与 impl::ctor_unlock
前面提到了可能部分控件上一帧创建, 部分控件下一帧创建. 那么如果一个控件被卡在中间怎么处理呢? 这就是 ```impl::ctor_lock``` 与 ```impl::ctor_unlock``` 这两条函数的作用.
Expand All @@ -147,6 +150,5 @@ MyControl::MyControl(UIControl* parent, const MetaControl& meta) : Super(impl::c

同上, 不建议直接调用```DataLock```. (默认控件中, UIBoxLayout可以接受卡在构造函数, 但是其超类UIScrollArea不能接受.) (以防万一就都加上)

### CUIWindow::~CUIWindow的超级锁
# 超级锁

与其他地方不同的是, CUIWindow析构操作会同时上两把锁, 因为Window数据(主窗口设计上)是放在栈上需要即时处理, 析构一个窗口需要保证绝对的安全
6 changes: 3 additions & 3 deletions doc/xul/stacks-and-decks.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

两个`label`元素都创建了一个大小为15像素的文字。首先是通过在左边和顶部添加一个1像素的偏移。这样的结果是重复绘制文字'Shadowed'但会与另一个有一点点的偏移。

这种方法的比使用`text-shadow`有一些优势,因为你可以完全将主体文字与阴影分开进行控制。它可以有自己的字体,下划线或者大小。(你甚至可以制作阴影闪烁的效果)。这在mozilla不支持CSS的文字阴影时也很有用。缺点是阴影的存在使得堆的尺寸变大了。。阴影效果对于创建禁用的按钮的外观很有用:
这种方法的比使用`text-shadow`有一些优势,因为你可以完全将主体文字与阴影分开进行控制。它可以有自己的字体,下划线或者大小。(你甚至可以制作阴影闪烁的效果)。这在mozilla不支持CSS的文字阴影时也很有用。缺点是阴影的存在使得栈的尺寸变大了。。阴影效果对于创建禁用的按钮的外观很有用:

- 例 2
- [源代码](./source/ex_stacks_2.xul)
Expand All @@ -53,13 +53,13 @@

这样安排文字和阴影颜色在某些平台上会产生禁用的外观

注意,鼠标点击或者按键按下的事件是在堆上顶部元素,即堆中的最后一个元素。就意味着按钮只有是堆中最后一个元素的时候才能工作
注意,鼠标点击或者按键按下的事件是在栈上顶部元素,即栈中的最后一个元素。就意味着按钮只有是栈中最后一个元素的时候才能工作

#

元素[deck](./deck.md)也是和[stack](./stack.md)一样只在顶部显示一个子元素,但是面板一次只显示一个子元素。这对向导接口非常有用,其中一系列相似的面板顺序显示。你可以通过使面板中的内容发生变化而只创建一个窗口,而不是创建多个独立的窗口和导航按钮。

与堆相似`deck`元素的直接子元素组成的页面。面板的显示页面可以通过改变设置`selectedIndex`属性来控制显示出来的子元素。索引是一个数字,可以指定哪一个页面将会显示。页面索引起始值为0.因此第一个子元素的page0,第二个是page1,等等。
与栈相似`deck`元素的直接子元素组成的页面。面板的显示页面可以通过改变设置`selectedIndex`属性来控制显示出来的子元素。索引是一个数字,可以指定哪一个页面将会显示。页面索引起始值为0.因此第一个子元素的page0,第二个是page1,等等。


以下は、デッキの例です。
Expand Down
4 changes: 2 additions & 2 deletions doc/xul/xul-tutorial.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Introduction

- This XUL tutorial was originally created by [Neil Deakin](http://www.xulplanet.com/ndeakin/). LongUI organized this document without authorized because of Mozilla marked XUL as "obsolete content".
- XULチュートリアルのオリジナルは、 [Neil Deakin](http://www.xulplanet.com/ndeakin/)が作成しました。MozillaがXULを “廃れたコンテンツ” にマーし、LongUI が無許可でこのドキュメントを整理しました。
- XULチュートリアルのオリジナルは、 [Neil Deakin](http://www.xulplanet.com/ndeakin/)が作成しました。MozillaがXULを “廃れたコンテンツ” にマークし、LongUI が無許可でこのドキュメントを整理しました。
- 这份XUL的教程是源自 [Neil Deakin](http://www.xulplanet.com/ndeakin/) 之手。因为Mozilla将XUL标记为"过时",所以LongUI擅自重新整理了该文档。

# The Box Model
Expand All @@ -24,7 +24,7 @@
- [Grids](./grids.en.md)
- [スタックとデッキ](./stacks-and-decks.jp.md)
- [グリッド](./grids.jp.md)
- [Stacks and Decks](./stacks-and-decks.zh.md)
- [栈与层](./stacks-and-decks.zh.md)
- [表格](./grids.zh.md)

# Toolbars and Menus
Expand Down

0 comments on commit 01359aa

Please sign in to comment.