302 lines
6.5 KiB
C++
Vendored
302 lines
6.5 KiB
C++
Vendored
/**
|
|
* @file dl_ui_msg_box.h
|
|
* @brief 消息框
|
|
*
|
|
*
|
|
* @version 1.0
|
|
* @author lveyou
|
|
* @date 22-05-11
|
|
*
|
|
* @note 带有标题、内容、按钮、关闭按钮的弹窗
|
|
*/
|
|
#pragma once
|
|
|
|
#ifndef DL_DISABLE_RENDER
|
|
#include "ui/dl_ui_button_sprite.h"
|
|
#include "system/dl_system.h"
|
|
|
|
namespace dl::UI
|
|
{
|
|
//! 消息框最大按钮数量
|
|
constexpr size_t NUM_MSG_BOX_BTN = 10;
|
|
|
|
//! UI消息框
|
|
class MsgBox
|
|
{
|
|
public:
|
|
/**
|
|
* @brief 构造
|
|
* @param[in] bg 九图精灵作为背景
|
|
* @param[in] txt_title 标题文本
|
|
* @param[in] txt 内容文本
|
|
* @param[in] btn 普通按钮
|
|
* @param[in] btn_close 关闭按钮
|
|
* @param[in] dx_btn 按钮(额外)间隔,艺术性调整
|
|
*
|
|
* @note 应该立即调用Set设置内容
|
|
*/
|
|
static MsgBox* Create(
|
|
Background* bg,
|
|
gcText txt_title,
|
|
gcText txt,
|
|
UI::ButtonSprite* btn,
|
|
UI::ButtonSprite* btn_close,
|
|
Float dx_btn = 0.0)
|
|
{
|
|
MsgBox* ret = new MsgBox;
|
|
Coor* coor = Coor::Create();
|
|
coor->SetPosition(toPosition(g_system->GetWindowSize() / 2u));
|
|
bg->SetUI(true);
|
|
|
|
ret->_coor = coor;
|
|
ret->_bg = bg;
|
|
ret->_txtTitle = txt_title;
|
|
ret->_txt = txt;
|
|
ret->_btn = btn;
|
|
ret->_btnClose = btn_close;
|
|
ret->_dxBtn = dx_btn;
|
|
|
|
ret->_refresh_coor();
|
|
ret->SetOrder(Z_DEFAULT_UI);
|
|
return ret;
|
|
}
|
|
|
|
MsgBox* Clone()
|
|
{
|
|
MsgBox* ret = new MsgBox(*this);
|
|
ret->_coor = _coor->Clone();
|
|
ret->_bg = _bg->Clone();
|
|
ret->_btn = _btn->Clone();
|
|
ret->_btnClose = _btnClose->Clone();
|
|
|
|
for (size_t i = 0; i < _allBtn.size(); ++i)
|
|
{
|
|
ret->_allBtn[i] = _allBtn[i]->Clone();
|
|
}
|
|
ret->_refresh_coor();
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief 设置内容
|
|
* @param[in] title 标题
|
|
* @param[in] info 内容
|
|
* @param[in] btns 按钮内容
|
|
*
|
|
*/
|
|
void Set(std::string_view title, std::string_view info, std::vector<std::string_view> all_btn)
|
|
{
|
|
_txtTitle->SetString(title);
|
|
if(_bAddTab)
|
|
_txt->SetString(std::string{ "\t" } + std::string{ info });
|
|
else
|
|
_txt->SetString(info);
|
|
|
|
//少了就新建按钮
|
|
_numBtn = all_btn.size();
|
|
if (_numBtn > _allBtn.size())
|
|
{
|
|
_allBtn.resize(_numBtn);
|
|
for (UI::ButtonSprite*& btn : _allBtn)
|
|
{
|
|
if (!btn)
|
|
{
|
|
btn = _btn->Clone();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (std::size_t i = 0; i < _numBtn; ++i)
|
|
{
|
|
_allBtn[i]->SetString(all_btn[i]);
|
|
}
|
|
|
|
//--------------------------------更新布局--------------------------------
|
|
Float w_btn = _btn->GetSize()[0]; //按钮宽度
|
|
Float h_btn = _btn->GetSize()[1];
|
|
//整体宽度为 按钮宽度 + 间隔(多一个)
|
|
Float w = w_btn * _numBtn + _dxBtn * (1 + _numBtn);
|
|
|
|
_txt->SetMaxW(w);//设置文本宽度
|
|
|
|
Float h_txt = _txt->GetSize()[1]; //文本高度
|
|
Float h_title = _txtTitle->GetSize()[1];//标题高度
|
|
//整体高度 标题 + 文本 + 按钮
|
|
Float h = h_title + h_txt * 1 + h_btn * 1;
|
|
_txt->SetCenter();
|
|
Position size{ w, h };
|
|
Position size_half{ size * 0.5f };
|
|
_bg->SetSize(size);
|
|
|
|
//设置位置
|
|
_bg->GetCoor()->SetPosition(toPosition(_bg->GetOffset()) - size_half);
|
|
_txtTitle->SetPositionAlign(-size_half, Align::LC);
|
|
_btnClose->GetCoor()->SetPosition({ size_half[0], -size_half[1] });
|
|
|
|
if (_numBtn > 0)
|
|
{
|
|
//偏移为 负的 按钮总宽度的一半(间隔少一个) + 半个按钮
|
|
Float sx_btn = (w_btn * _numBtn + _dxBtn * (_numBtn - 1)) * -0.5_f + w_btn * 0.5_f;
|
|
for (std::size_t i = 0; i < _numBtn; ++i)
|
|
{
|
|
_allBtn[i]->GetCoor()->SetPosition({ sx_btn + i * (w_btn + _dxBtn), size_half[1] });
|
|
}
|
|
}
|
|
|
|
}
|
|
/**
|
|
* @brief 设置内容,以语言文件配置的名称
|
|
*
|
|
*/
|
|
void Set(std::string_view str)
|
|
{
|
|
std::string_view str_title = lang("msg_box", std::string{ str } + "_title");
|
|
std::string_view str_info = lang("msg_box", std::string{ str } + "_info");
|
|
std::vector<std::string_view> all_btn;
|
|
for (std::size_t i = 0; i < NUM_MSG_BOX_BTN; ++i)
|
|
{
|
|
std::string str_name = fmt::format("{}_{}", str, i);
|
|
auto str = g_lang->GetCheck("msg_box", str_name);
|
|
if (!str.has_value())
|
|
{
|
|
break;
|
|
}
|
|
all_btn.push_back(str.value());
|
|
}
|
|
|
|
Set(str_title, str_info, all_btn);
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
_btnClose->Update();
|
|
for (size_t i = 0; i < _numBtn; ++i)
|
|
{
|
|
_allBtn[i]->Update();
|
|
}
|
|
|
|
if (_posPick)
|
|
{
|
|
if (g_input->KeyUp(MouseCode::LEFT))
|
|
_posPick.reset();
|
|
}
|
|
else
|
|
{
|
|
if (g_input->KeyDown(MouseCode::LEFT) && IsPickupTitle())
|
|
{
|
|
_posPick = _coor->WorldToThis(toPosition(g_input->GetCursorPosition()));
|
|
}
|
|
}
|
|
|
|
//左键拖动
|
|
if (_posPick)
|
|
{
|
|
Point pos = g_input->GetCursorPosition();
|
|
_coor->SetPosition(toPosition(pos) - _posPick.value());
|
|
}
|
|
}
|
|
|
|
void Render()
|
|
{
|
|
_bg->Render();
|
|
_txtTitle->Render();
|
|
_txt->Render();
|
|
}
|
|
/**
|
|
* @brief 返回点击按钮索引,返回-1代表没有点击
|
|
*/
|
|
size_t GetClick()
|
|
{
|
|
for (size_t i = 0; i < _numBtn; ++i)
|
|
{
|
|
if (_allBtn[i]->IsClick())
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
/**
|
|
* @brief 是否点击了关闭按钮
|
|
*/
|
|
bool IsClickClose()
|
|
{
|
|
return _btnClose->IsClick();
|
|
}
|
|
/**
|
|
* @brief 是否选中标题栏
|
|
*/
|
|
bool IsPickupTitle()
|
|
{
|
|
if (_bg->IsPickup())
|
|
{//按钮会屏蔽bg的IsPickup
|
|
Position pos = _txtTitle->GetCoor()->WorldToThis(toPosition(g_input->GetCursorPosition()));
|
|
if (pos[1] < _txtTitle->GetSize()[1])
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void SetOrder(float order)
|
|
{
|
|
_txt->SetOrder(Math::OffsetOrder(order, 0, 0, -1));
|
|
_txtTitle->SetOrder(Math::OffsetOrder(order, 0, 0, -1));
|
|
_btnClose->SetOrder(Math::OffsetOrder(order, 0, 0, -1));
|
|
_btn->SetOrder(Math::OffsetOrder(order, 0, 0, -1));
|
|
for (auto& iter : _allBtn)
|
|
{
|
|
iter->SetOrder(Math::OffsetOrder(order, 0, 0, -1));
|
|
}
|
|
_bg->SetOrder(Math::OffsetOrder(order, 0, 0, 0));
|
|
}
|
|
|
|
~MsgBox()
|
|
{
|
|
delete _coor;
|
|
delete _bg;
|
|
delete _btn;
|
|
delete _btnClose;
|
|
for (auto& iter : _allBtn)
|
|
delete iter;
|
|
}
|
|
private:
|
|
MsgBox():
|
|
_coor{nullptr},
|
|
_bg{nullptr},
|
|
_btn{nullptr},
|
|
_btnClose{nullptr},
|
|
_numBtn{0},
|
|
_bAddTab{true}
|
|
{}
|
|
Coor* _coor;
|
|
|
|
Background* _bg;
|
|
gcText _txtTitle;
|
|
gcText _txt;
|
|
UI::ButtonSprite* _btn;
|
|
UI::ButtonSprite* _btnClose;
|
|
|
|
//动态改变长度,多余的不会自动删除,所以需要标记使用数量
|
|
std::vector<UI::ButtonSprite*> _allBtn;
|
|
std::size_t _numBtn;
|
|
|
|
Float _dxBtn;
|
|
|
|
std::optional<Position> _posPick;//被拾取位置(差值,相加即可)(直到再抬起)
|
|
bool _bAddTab;//添加段首缩进
|
|
|
|
void _refresh_coor()
|
|
{
|
|
_bg->GetCoor()->SetParent(_coor);
|
|
_txtTitle->GetCoor()->SetParent(_coor);
|
|
_txt->GetCoor()->SetParent(_coor);
|
|
_btn->GetCoor()->SetParent(_coor);
|
|
_btnClose->GetCoor()->SetParent(_coor);
|
|
|
|
for (size_t i = 0; i < _allBtn.size(); ++i)
|
|
{
|
|
_allBtn[i]->GetCoor()->SetParent(_coor);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#endif |