SDL中文论坛
标题:
set_label、set_visible后的重布局机制
[打印本页]
作者:
ancientcc
时间:
2017-12-22 11:01
标题:
set_label、set_visible后的重布局机制
本帖最后由 ancientcc 于 2017-12-22 11:18 编辑
set_label,要设置的内容尺寸超过控件当前的渲染尺寸,就须要增大渲染尺寸,于是须要重布局。set_visible改变一个控件的显示/隐藏状态后自然须要布局。
机制涉及到三个函数。
bool can_invalidate_layout() const {
return can_invalidate_layout_;
}
virtual void invalidate_layout(twidget* widget) {}
virtual void validate_visible_pre_change(const twidget& widget) const {}
复制代码
这三个函数在twidget声明,can_invalidate_layout只是twidget实现,后两个是虚函数。
作为一个目标,不要再让app直接调用invalidate_layout
。Rose内部要能处理掉所有须要重布局的操作。
处理逻辑
以下假设当前控件是current。
什么时候须要重布局
通用条件。1)不是悬浮控件,2)disable_invalidate_layout是false。3)窗口至少已布局过一次。
set_label的特殊条件。1)config_->label_is_text = true。2)visible_ != twidget::INVISIBLE。3)算出的标称尺寸的高度不是渲染尺寸高度,包括超过和小于。
为什么要增加disable_invalidate_layout?举个例子,listbox在增加一行时,insert_row会调用set_label,但它退出前会处理重布局,于是set_label就没必要再触发重布局机制了。tdisable_invalidate_layout_lock用于自动管理这变量。
找到能处理重布局的控件
从current起,不断向上找父控件,记为widget,判断widget的can_invalidate_layout()是否返回true,是true则认为已找到能处理重布局的控件,结束查找。
twindow指向窗口,是根,它的can_invalidate_layout()总是返回true。
当前两类控件会让can_invalidate_layout()返回true。一是从tscroll_container派生的滚动控件,二是twindow。
处理重布局
以current为参数调用widget.invalidate_layout(current)。
validate_visible_pre_change
为什么要增加它?一些控件不允许app直接调用set_visible改变孩子的显示状态。举个例子,report不允许app直接调用set_visible改变当中单元的状态,而是应该用set_item_visible。为防止app依然调用set_visible,这时应该直接抛出异常,提示app改去调用set_item_visible。
validate_visible_pre_change执行的都是assert操作,目的是防止app错误调用api。
除了report,listbox也重载这函数,防止app调用set_visible直接改变哪行(toggle_panel)的显示状态。
欢迎光临 SDL中文论坛 (http://www.libsdl.cn/bbs/)
Powered by Discuz! X3.3