SDL中文论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 3782|回复: 0
打印 上一主题 下一主题

[gui2] set_label、set_visible后的重布局机制

[复制链接]

187

主题

346

帖子

2450

积分

版主

Rank: 7Rank: 7Rank: 7

积分
2450
跳转到指定楼层
楼主
发表于 2017-12-22 11:01:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 ancientcc 于 2017-12-22 11:18 编辑

set_label,要设置的内容尺寸超过控件当前的渲染尺寸,就须要增大渲染尺寸,于是须要重布局。set_visible改变一个控件的显示/隐藏状态后自然须要布局。

机制涉及到三个函数。
  1. bool can_invalidate_layout() const {
  2.         return can_invalidate_layout_;
  3. }
  4. virtual void invalidate_layout(twidget* widget) {}
  5. 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)的显示状态。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|丽谷软件|libsdl.cn

GMT+8, 2024-5-20 03:25 , Processed in 0.053798 second(s), 19 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表