#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