Add parent-child relationship of the control tree and bubble-style invalidation propagation.
This commit is contained in:
1 parent
df881f81bf
commit
db59ca7365
4 files changed
+80
-16
No files matched your search
@@ -41,6 +41,7 @@
|
||||
- 修复了单行 `TextBox`(如 demo 中的 Search Box)输入光标和文本区域未垂直居中的问题
|
||||
- 修复了单行 `TextBox` 在垂直居中后输入法候选框未同步跟随文本区域下移的问题
|
||||
- 新增一版场景级 invalidation 机制:控件现可通过 `InvalidateMeasure` / `InvalidateArrange` / `InvalidateVisual` 统一声明布局或重绘失效,`Scene` / `Window` 会在下一次绘制前自动补做布局,减少到处手动 `Relayout()` 的耦合
|
||||
- 补充了控件树父子关系和冒泡式失效传播:容器在收养子控件时会建立 parent 链,子控件的布局/重绘失效会先沿控件树向上汇聚,再交给根场景统一处理,为后续做局部布局优化打基础
|
||||
|
||||
## 构建
|
||||
|
||||
@@ -107,6 +108,7 @@ build/bin/Debug/msimeui-demo.exe
|
||||
## 后续工作
|
||||
|
||||
- 继续把场景级 invalidation 细化为局部布局和局部重绘,减少全树重排成本
|
||||
- 基于现有 parent 链继续引入更细粒度的 subtree dirty 标记和可缓存测量结果
|
||||
- 继续完善 `TextBox` 的输入、样式和布局能力
|
||||
- 增加菜单、弹出层、overlay 和更完整的命中/焦点管理
|
||||
- 引入资源字典、主题和声明式界面描述
|
||||
@@ -95,8 +95,12 @@ class Visual
|
||||
const RectF &GetBounds() const;
|
||||
|
||||
protected:
|
||||
void AdoptChild(const std::shared_ptr<Visual> &child);
|
||||
void ReleaseChild(const std::shared_ptr<Visual> &child);
|
||||
bool HasExplicitWidth() const;
|
||||
bool HasExplicitHeight() const;
|
||||
void SetParent(Visual *parent);
|
||||
Visual *GetParent() const;
|
||||
|
||||
Thickness margin_ = {};
|
||||
Thickness padding_ = {};
|
||||
@@ -110,6 +114,7 @@ class Visual
|
||||
VerticalAlignment verticalAlignment_ = VerticalAlignment::Leading;
|
||||
SizeF desiredSize_ = {};
|
||||
RectF bounds_ = {};
|
||||
Visual *parent_ = nullptr;
|
||||
Window *window_ = nullptr;
|
||||
};
|
||||
|
||||
|
||||
+10
-8
@@ -1082,16 +1082,17 @@ TabControl::TabControl(float headerHeight) : headerHeight_(headerHeight)
|
||||
|
||||
void TabControl::AddTab(std::wstring title, std::shared_ptr<Visual> content)
|
||||
{
|
||||
AdoptChild(content);
|
||||
tabs_.push_back({std::move(title), std::move(content)});
|
||||
if (tabs_.back().content && window_)
|
||||
{
|
||||
tabs_.back().content->Attach(window_);
|
||||
}
|
||||
InvalidateMeasure();
|
||||
}
|
||||
|
||||
void TabControl::ClearTabs()
|
||||
{
|
||||
for (auto &tab : tabs_)
|
||||
{
|
||||
ReleaseChild(tab.content);
|
||||
}
|
||||
tabs_.clear();
|
||||
headerRects_.clear();
|
||||
selectedIndex_ = 0;
|
||||
@@ -1328,20 +1329,21 @@ Accordion::Accordion(float headerHeight) : headerHeight_(headerHeight)
|
||||
|
||||
void Accordion::AddSection(std::wstring title, std::shared_ptr<Visual> content, bool expanded)
|
||||
{
|
||||
AdoptChild(content);
|
||||
sections_.push_back({std::move(title), std::move(content), expanded});
|
||||
if (!allowMultipleExpanded_ && expanded)
|
||||
{
|
||||
CollapseOtherSections(sections_.size() - 1);
|
||||
}
|
||||
if (sections_.back().content && window_)
|
||||
{
|
||||
sections_.back().content->Attach(window_);
|
||||
}
|
||||
InvalidateMeasure();
|
||||
}
|
||||
|
||||
void Accordion::ClearSections()
|
||||
{
|
||||
for (auto §ion : sections_)
|
||||
{
|
||||
ReleaseChild(section.content);
|
||||
}
|
||||
sections_.clear();
|
||||
headerRects_.clear();
|
||||
contentRects_.clear();
|
||||
|
||||
+63
-8
@@ -183,6 +183,12 @@ HCURSOR Visual::GetCursor() const
|
||||
|
||||
void Visual::InvalidateMeasure()
|
||||
{
|
||||
if (parent_)
|
||||
{
|
||||
parent_->InvalidateMeasure();
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_)
|
||||
{
|
||||
window_->InvalidateMeasure();
|
||||
@@ -191,6 +197,12 @@ void Visual::InvalidateMeasure()
|
||||
|
||||
void Visual::InvalidateArrange()
|
||||
{
|
||||
if (parent_)
|
||||
{
|
||||
parent_->InvalidateArrange();
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_)
|
||||
{
|
||||
window_->InvalidateArrange();
|
||||
@@ -199,6 +211,12 @@ void Visual::InvalidateArrange()
|
||||
|
||||
void Visual::InvalidateVisual()
|
||||
{
|
||||
if (parent_)
|
||||
{
|
||||
parent_->InvalidateVisual();
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_)
|
||||
{
|
||||
window_->Invalidate();
|
||||
@@ -411,17 +429,51 @@ bool Visual::HasExplicitWidth() const
|
||||
return explicitWidth_ >= 0.0f;
|
||||
}
|
||||
|
||||
void Visual::AdoptChild(const std::shared_ptr<Visual> &child)
|
||||
{
|
||||
if (!child)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
child->SetParent(this);
|
||||
if (window_)
|
||||
{
|
||||
child->Attach(window_);
|
||||
}
|
||||
}
|
||||
|
||||
void Visual::ReleaseChild(const std::shared_ptr<Visual> &child)
|
||||
{
|
||||
if (child && child->GetParent() == this)
|
||||
{
|
||||
child->SetParent(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool Visual::HasExplicitHeight() const
|
||||
{
|
||||
return explicitHeight_ >= 0.0f;
|
||||
}
|
||||
|
||||
void Visual::SetParent(Visual *parent)
|
||||
{
|
||||
parent_ = parent;
|
||||
}
|
||||
|
||||
Visual *Visual::GetParent() const
|
||||
{
|
||||
return parent_;
|
||||
}
|
||||
|
||||
void Panel::AddChild(std::shared_ptr<Visual> child)
|
||||
{
|
||||
if (child && window_)
|
||||
if (!child)
|
||||
{
|
||||
child->Attach(window_);
|
||||
return;
|
||||
}
|
||||
|
||||
AdoptChild(child);
|
||||
children_.push_back(std::move(child));
|
||||
InvalidateMeasure();
|
||||
}
|
||||
@@ -686,6 +738,7 @@ void WrapPanel::Render(DeviceResources &deviceResources)
|
||||
|
||||
ScrollViewer::ScrollViewer(std::shared_ptr<Visual> content) : content_(std::move(content))
|
||||
{
|
||||
AdoptChild(content_);
|
||||
}
|
||||
|
||||
SizeF ScrollViewer::Measure(const SizeF &availableSize)
|
||||
@@ -963,10 +1016,12 @@ void Grid::AddColumn(GridLength length)
|
||||
|
||||
void Grid::AddChild(std::shared_ptr<Visual> child, size_t row, size_t column, size_t rowSpan, size_t columnSpan)
|
||||
{
|
||||
if (child && window_)
|
||||
if (!child)
|
||||
{
|
||||
child->Attach(window_);
|
||||
return;
|
||||
}
|
||||
|
||||
AdoptChild(child);
|
||||
children_.push_back({std::move(child), {row, column, std::max<size_t>(rowSpan, 1), std::max<size_t>(columnSpan, 1)}, {}});
|
||||
InvalidateMeasure();
|
||||
}
|
||||
@@ -1197,15 +1252,15 @@ std::vector<float> Grid::ResolveTrackSizes(const std::vector<GridLength> &defini
|
||||
|
||||
Container::Container(std::shared_ptr<Visual> child) : child_(std::move(child))
|
||||
{
|
||||
AdoptChild(child_);
|
||||
}
|
||||
|
||||
void Container::SetChild(std::shared_ptr<Visual> child)
|
||||
{
|
||||
ReleaseChild(child_);
|
||||
|
||||
child_ = std::move(child);
|
||||
if (child_ && window_)
|
||||
{
|
||||
child_->Attach(window_);
|
||||
}
|
||||
AdoptChild(child_);
|
||||
InvalidateMeasure();
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user