Files
dl_old/dl/ui/dl_ui_progress_bar.cpp
2026-09-08 12:18:03 +08:00

179 lines
4.2 KiB
C++

#include "ui/dl_ui_progress_bar.h"
#ifndef DL_DISABLE_RENDER
#include "ui/dl_ui_manager.h"
namespace dl::UI
{
//! 创建自身panel,并把子元素挂载进去
void ProgressBar::_init_panel()
{
_panel = g_ui->CreatePanel();
_panel->SetAutoRun(false);
_panel->SetAutoCoor(false);
_panel->SetOrderMode(Panel::FORCE);
_panel->SetPickupMode(Panel::E_ELEMENT);
// 子元素坐标系挂到自身panel,使其跟随整体移动
if (_bg) _panel->Add(_bg);
if (_mid) _panel->Add(_mid);
if (_txt) _panel->Add(_txt);
// 保存 mid 原图大小(填充区域默认用它)
if (_mid)
_sizeMidOrigin = _mid->GetSize();
_panel->SetSize(_bg->GetSize());
// 文本默认居中
_refresh_text_pos();
}
//! 刷新文本位置与旋转(默认居中,竖向按方向旋转)
void ProgressBar::_refresh_text_pos()
{
if (!_txt)
return;
Coor* coor = _txt->GetCoor();
Position size = _bg->GetSize();
Position size_txt = _txt->GetText()->GetSize();
float tw = size_txt.w;
float th = size_txt.h;
switch (_dir)
{
case Align::Dir4::RIGHT:
case Align::Dir4::LEFT:
// 水平:居中,不旋转
coor->SetRotate(0);
coor->SetPosition({ (size.w - tw) * 0.5f, (size.h - th) * 0.5f });
break;
case Align::Dir4::BOTTOM:
// 向下填充:顺时针旋转90°,居中
coor->SetRotate(Math::PIF(1, 2));
coor->SetPosition({ size.w * 0.5f + th * 0.5f, size.h * 0.5f - tw * 0.5f });
break;
case Align::Dir4::TOP:
// 向上填充:逆时针旋转90°,居中
coor->SetRotate(-Math::PIF(1, 2));
coor->SetPosition({ size.w * 0.5f - th * 0.5f, size.h * 0.5f + tw * 0.5f });
break;
}
}
ProgressBar::~ProgressBar()
{
// 接管子元素生命周期(子元素挂载在panel上,随panel一并释放)
g_ui->DeletePanel(_panel, true);
}
void ProgressBar::_refresh_mid()
{
if (!_mid)
return;
// mid 绘制区域:空则以 mid 原图大小
RectF rect = _rectMid;
if (Math::IsRectEmpty(rect))
rect = { 0, 0, _sizeMidOrigin.w, _sizeMidOrigin.h };
float rect_w = rect[2] - rect[0];
float rect_h = rect[3] - rect[1];
Position size{}; // 填充图大小
Position pos{}; // 填充图偏移(左/上方向填充时,对齐到对侧)
switch (_dir)
{
case Align::Dir4::RIGHT:
// 水平填充:宽随进度变化
size = { rect_w * _progress, rect_h };
pos = { rect[0], rect[1] };
break;
case Align::Dir4::LEFT:
size = { rect_w * _progress, rect_h };
pos = { rect[0] + rect_w - size.w, rect[1] };
break;
case Align::Dir4::BOTTOM:
// 垂直填充:高随进度变化
size = { rect_w, rect_h * _progress };
pos = { rect[0], rect[1] };
break;
case Align::Dir4::TOP:
size = { rect_w, rect_h * _progress };
pos = { rect[0], rect[1] + rect_h - size.h };
break;
}
_mid->SetSize(size);
_mid->GetCoor()->SetPosition(pos);
}
dl::UI::ProgressBar* ProgressBar::Create(UI::Background* bg, UI::Background* mid, UI::Text* txt /*= nullptr*/)
{
ProgressBar* ret = new ProgressBar;
ret->_bg = bg;
ret->_mid = mid;
ret->_txt = txt;
ret->_mid->SetUI(false);
// 挂载子元素到自身panel
ret->_init_panel();
ret->_order = Z_DEFAULT_UI;
ret->SetOrder(ret->_order);
ret->_init_cpt();
ret->_cptElemData._size = ret->_bg->GetSize();
return ret;
}
dl::UI::ProgressBar* ProgressBar::Clone()
{
ProgressBar* ret = new ProgressBar;
ret->_bg = _bg ? _bg->Clone() : nullptr;
ret->_mid = _mid ? _mid->Clone() : nullptr;
ret->_txt = _txt ? _txt->Clone() : nullptr;
ret->_progress = _progress;
ret->_progressK = _progressK;
ret->_cptElemData = _cptElemData;
ret->_order = _order;
ret->_dir = _dir;
ret->_fmt = _fmt;
ret->_rectMid = _rectMid;
ret->_sizeMidOrigin = _sizeMidOrigin;
// 挂载克隆出的子元素到自身panel
ret->_init_panel();
ret->_init_cpt();
ret->SetOrder(ret->_order);
// 恢复填充图尺寸(Background::Clone不会复制元素大小)
ret->_refresh_mid();
ret->_refresh_text();
return ret;
}
void ProgressBar::_refresh_text()
{
if (!_txt || _fmt.empty())
return;
float percent = _progress * _progressK;
std::string str = fmt::vformat(_fmt, fmt::make_format_args(percent));
_txt->SetString(str);
_refresh_text_pos();
}
void ProgressBar::SetDir(Align::Dir4 dir)
{
_dir = dir;
_refresh_mid();
_refresh_text_pos();
}
}
#endif