Files
dl_old/dl/ui/dl_ui_panel.cpp

674 lines
13 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "ui/dl_ui_panel.h"
#ifndef DL_DISABLE_RENDER
#include "io/dl_file.h"
#include "ui/dl_ui_manager.h"
#include "ui/dl_ui_edit_box.h"
#include "base/dl_range_find.h"
#include "system/dl_system.h"
namespace dl::UI
{
void Panel::AddCpt(Components* cpt)
{
//ElementData组件处理
Cpt::ElementData* ele_data = cpt->Get<Cpt::ElementData>();
Position offset{};
Position size{};
int order_offset{};
if (ele_data)
{
size = ele_data->GetSize();
// 大小处理
if (ele_data->_bParentW)
size.w = _size.w;
if (ele_data->_bParentH)
size.h = _size.h;
if (ele_data->_bParentW || ele_data->_bParentH)
{
Cpt::SetSize* comp_size = cpt->Get<Cpt::SetSize>();
if (comp_size)
comp_size->Call(size);
else
log_warn0("元素没有SetSize成员!");
}
// 计算offset
offset = ele_data->GetOffset();
order_offset = ele_data->GetOrderOffset();
}
// 位置计算
Position pos = offset;
_locator.ExGet(_allEle.size(), toSizeNeg2Zero(size), pos);
// 组件处理
for (AnyType& iter : cpt->GetVectorAny())
{
if (auto comp = iter.Cast<Cpt::GetCoor>())
{
Coor* coor = comp->Call();
coor->SetParent(_coor);
// 最终坐标为 自身ElementData对齐 + 定位器
coor->SetPosition(pos);
}
else if (auto comp = iter.Cast<Cpt::SetOrder>())
{
comp->Call(Math::OffsetOrder(_order, 0, order_offset));
}
else if (auto comp = iter.Cast<Panel*>())
{// 添加自己为父节点
*comp = this;
}
}
_allEle.push_back(cpt);
}
void Panel::DelCpt(Components* cpt)
{
auto iter = std::find(_allEle.begin(), _allEle.end(), cpt);
if(iter != _allEle.end())
_allEle.erase(iter);
}
void Panel::Add(std::string_view json_path)
{
std::ifstream ifs = File::Get(json_path);
if (!ifs.is_open())
{
log_err("json文件并不存在:{}", json_path);
return;
}
json j = json::parse(ifs);
for (auto& iter : j)
{
std::string type;
std::string str;
Json::Get(iter, "type", type);
Json::Get(iter, "string", str);
//解析type
std::vector<std::string> vec_type = String::Split(type, '.');
if (vec_type.size() != 2)
{
log_err0("元素的type应该有两个字段!");
continue;
}
ElementType ele_type = String2ElementType(vec_type[0]);
if (ele_type == ElementType::UNKNOWN)
continue;
if (ele_type == ElementType::BUTTON)
{
ButtonSprite* btn = g_ui->CreateButtonSprite(vec_type[1]);
btn->SetString(lang_auto(str));
Add(btn);
}
//debug(type + str);
}
}
void Panel::AddPanel(Panel* child)
{
g_ui->SetPanelParent(child, this);
}
Panel* Panel::Clone()
{
Panel* ret = g_ui->CreatePanel(_node->GetParent()->GetValue());
NTree<Panel*>::Node* node = ret->_node;
Coor* coor = ret->_coor;
*ret = *this;
ret->_coor = coor;
ret->_coor->SetParent(_coor->GetParent());
ret->_node = node;
// 复制子节点
for(auto node_child : _node->GetChild())
{
g_ui->SetPanelParent(node_child->GetValue()->Clone(), ret);
}
ret->_allEle.clear();
for (Components* cpt : _allEle)
{
Cpt::Clone* comp = cpt->Get<Cpt::Clone>();
if (!comp)
{
log_err0("可复制panel的元素必须包含Clone组件!");
continue;
}
ret->AddCpt(comp->Call());
}
return ret;
}
void Panel::SetLocator(std::string_view name)
{
SetLocator(g_ui->CreateLocator(name));
}
void Panel::Update()
{
if (_bUpdate)
{
log_err("已经调用过Update!");
return;
}
_bUpdate = true;
// 先优先级组件(drag)
for (Components* cpt : _allEle)
{
_update_cpt_drag(cpt);
}
// 位置刷新
if (_bNeedRefreshPos)
{
_bNeedRefreshPos = false;
_refresh_pos(GetParentSize());
}
// 后优先级组件
for (Components* cpt : _allEle)
{
if (Cpt::ElementData* comp = cpt->Get<Cpt::ElementData>())
{
if(!comp->_bRunAble || !comp->_bUpdateAble)
continue;
}
if (Cpt::Update* comp = cpt->Get<Cpt::Update>())
comp->Call();
_update_cpt_radio(cpt);
}
_update_child();
}
void Panel::UpdateRadio()
{
// todo
for (auto& iter : _node->GetChild())
{
Panel* child = iter->GetValue();
if (child->GetSelect())
{
for (auto& iter1 : _node->GetChild())
{
Panel* child1 = iter1->GetValue();
if (child != child1)
{
child1->SetSelectAll(false);
}
}
}
}
}
void Panel::Render()
{
if (g_ui->IsHide())
return;
if (_bRender)
{
log_warn("已经调用过Render:{}", _name);
return;
}
// 这里包含自动调用、手动调用的情况,但自动调用后执行
_bRender = true;
// TODO panel默认穿透
/*if (_pickupMode & E_SIZE)
{
if (IsPickup())
{
g_factory->SetOrderPickup(_order);
}
}*/
for (Components* cpt : _allEle)
{
if (Cpt::ElementData* comp = cpt->Get<Cpt::ElementData>())
{
if (!comp->_bRunAble || !comp->_bRenderAble)
continue;
}
Cpt::Render* comp = cpt->Get<Cpt::Render>();
if (!comp)
continue;
comp->Call();
}
_render_child();
}
void Panel::_refresh_pos(const Position& size)
{
assert(_bAutoCoor);
_coor->SetPosition(_posPixel + _posScale * size - Align::Size2Anchor(GetSize(), _align) + Align::Dir2Offset(GetSize(), _dir));
for (auto& iter : _node->GetChild())
{
Panel* child = iter->GetValue();
if (child->_bAutoCoor)
child->_refresh_pos(GetSize());
}
}
void Panel::_update_child()
{
for (auto& iter : _node->GetChild())
{
Panel* child = iter->GetValue();
if (child->_bAutoRun)
{
child->Update();
}
}
}
void Panel::_render_child()
{
for (auto& iter : _node->GetChild())
{
Panel* child = iter->GetValue();
if (child->_bAutoRun)
{
child->Render();
}
else if(child->_bAutoRender && child->_bUpdate && !child->_bRender)
{
child->Render();
}
}
}
void Panel::_refresh_size()
{
if (_align != Align::LT)
{
assert(_bAutoCoor);
_bNeedRefreshPos = true; // 修改大小会影响自己的对齐,即Align
}
if (_bSizeFull)
{
// 父节点大小
if (_node->GetParent())
{
_size = _node->GetParent()->GetValue()->_size;
}
else
{// 顶层以窗口大小
_size = toPosition(g_system->GetWindowSize()) / g_ui->GetScale();
}
}
// 子元素相关处理
for (auto& iter : _allEle)
{
if (UI::Sprite* spr = iter->Cast<UI::Sprite>())
{
if (spr->GetAutoSize() != Sprite::AutoSize::NONE)
{
spr->SetMode(spr->GetAutoSize(), spr->GetFillMode());
}
}
else if (UI::Background* bg = iter->Cast<UI::Background>())
{
bg->RefreshSize();
}
// 跟随大小处理
if (Cpt::ElementData* comp = iter->Get<Cpt::ElementData>())
{
Position size;
bool change_size = false;
if (comp->_bParentW && comp->_bParentH)
{
size = GetSize();
change_size = true;
}
else if (comp->_bParentW || comp->_bParentH)
{
Cpt::GetSize* comp_get_size = iter->Get<Cpt::GetSize>();
if (comp_get_size)
{
size = comp_get_size->Call();
if (comp->_bParentW)
size.w = GetSize().w;
if (comp->_bParentH)
size.h = GetSize().h;
change_size = true;
}
}
if (change_size)
{
Cpt::SetSize* comp_size = iter->Get<Cpt::SetSize>();
if (comp_size)
comp_size->Call(size);
}
}
}
}
void Panel::OnChangeElementData(Components* cpt)
{
std::size_t i = Find::FirstIndex(_allEle, cpt);
if (i == -1)
{
log_err0("不属于Panel的成员!");
return;
}
//ElementData组件处理
Cpt::ElementData* ele_data = cpt->Get<Cpt::ElementData>();
if (!ele_data)
{
log_err0("ElementData不存在!");
return;
}
Position offset = ele_data->GetOffset();
Position size = ele_data->GetSize();
// 位置计算
Position pos = offset;
_locator.ExGet(i, toSizeNeg2Zero(size), pos);
// 组件处理
for (AnyType& iter : cpt->GetVectorAny())
{
if (auto comp = iter.Cast<Cpt::GetCoor>())
{
Coor* coor = comp->Call();
coor->SetParent(_coor);
coor->SetPosition(pos);
}
}
}
void Panel::_refresh_order()
{
switch (_orderMode)
{
case Panel::AUTO:
{
auto node_parent = _node->GetParent();
if (node_parent)
{
Panel* parent = node_parent->GetValue();
size_t i = parent->GetChildIndex(this);
_order = Math::OffsetOrder(parent->_order, 0, -(int)i - 1);
}
}
break;
case Panel::CUSTOM:
{
auto node_parent = _node->GetParent();
if (node_parent)
{
Panel* parent = node_parent->GetValue();
size_t i = parent->GetChildIndex(this);
_order = Math::OffsetOrder(parent->_order, 0, _orderInParent);
}
}
break;
case Panel::FORCE:
default:
break;
}
// 更新元素
for (Components*& cpt : _allEle)
{
if (auto comp = cpt->Get<Cpt::SetOrder>())
{
comp->Call(Math::OffsetOrder(_order, 0, 0, -1));
}
}
// 更新子节点
for (auto& iter : _node->GetChild())
{
Panel* child = iter->GetValue();
child->_refresh_order();
}
}
dl::UI::Button* Panel::ExGetButton(size_t n /*= 0*/, bool show_log /*= true*/)
{
auto* btn = GetElement<UI::Button>(n);
if (btn)
return btn;
if (show_log)
log_warn("获取第{}个 Button失败!", n);
return nullptr;
}
dl::UI::ButtonSprite* Panel::ExGetButtonSprite(size_t n, bool show_log)
{
auto* btn = GetElement<UI::Button>(n);
auto* ret = dynamic_cast<UI::ButtonSprite*>(btn);
if (ret)
return ret;
if (show_log)
log_warn("获取第{}个 ButtonSprite失败!", n);
return nullptr;
}
dl::UI::ButtonSprite9* Panel::ExGetButtonSprite9(size_t n /*= 0*/, bool show_log /*= true*/)
{
auto* btn = GetElement<UI::Button>(n);
auto* ret = dynamic_cast<UI::ButtonSprite9*>(btn);
if (ret)
return ret;
if (show_log)
log_warn("获取第{}个 ButtonSprite9失败!", n);
return nullptr;
}
dl::UI::EditBox* Panel::ExGetEditBox(size_t n /*= 0*/, bool show_log)
{
auto ret = GetElement<UI::EditBox>(n);
if (ret)
return ret;
if (show_log)
log_warn("获取第{}个 EditBox失败!", n);
return nullptr;
}
dl::UI::Text* Panel::ExGetText(size_t n /*= 0*/, bool show_log)
{
auto ret = GetElement<UI::Text>(n);
if (ret)
return ret;
if (show_log)
log_warn("获取第{}个 Text失败!", n);
return nullptr;
}
dl::UI::Background* Panel::ExGetBackground(size_t n /*= 0*/, bool show_log /*= true*/)
{
auto ret = GetElement<UI::Background>(n);
if (ret)
return ret;
if (show_log)
log_warn("获取第{}个 Background失败!", n);
return nullptr;
}
void Panel::ExSetString(std::string_view str, size_t n /*= 0*/)
{
auto txt = ExGetText(n, false);
if (txt)
{
txt->SetString(str);
return;
}
auto btn = ExGetButton(n, false);
if (btn)
{
btn->SetString(str);
return;
}
auto btn9 = ExGetButtonSprite9(n, false);
if (btn9)
{
btn9->SetString(str);
return;
}
log_warn("设置 Panel第{}个 String失败!", n);
}
void Panel::_update_cpt_drag(Components* cpt)
{
// 拖拽组件处理
Cpt::Drag* drag = cpt->Get<Cpt::Drag>();
if (!drag)
return;
if (!drag->_bEnable)
return;
//
Cpt::IsPickup* cpt_pickup = cpt->Get<Cpt::IsPickup>();
if (!cpt_pickup)
return;
//
Coor* coor;
if (drag->_bControlPanel)
coor = _coor;
else
{
Cpt::GetCoor* get_coor = cpt->Get<Cpt::GetCoor>();
if (get_coor)
coor = get_coor->Call();
}
Position pos_pre = coor->GetPosition();
drag->Update(coor, cpt_pickup->Call());
Position pos_dt = coor->GetPosition() - pos_pre;
if (drag->_bControlPanel)
{
// drag->Update 已更新
_posPixel += pos_dt;
//log_info("拖拽:{} dt {}", to_string(_posPixel), to_string(pos_dt));
}
}
void Panel::_update_cpt_radio(Components* cpt)
{
// 如果自己是radio且打开,则将其它radio变为非open
if (UI::Button* c = cpt->Cast<UI::Button>())
{
if (c->GetMode() == UI::Button::Mode::RADIO
&& c->IsSelect())
{
for (Components* cpt1 : _allEle)
{
if (cpt1 != cpt)
{
UI::Button* c1 = cpt1->Cast<UI::Button>();
if (c1 && c1->GetMode() == UI::Button::Mode::RADIO)
{
c1->SetSelect(false);
}
}
}
}
}
}
dl::UI::Panel* Panel::GetChildSelect()
{
for (auto& iter : _node->GetChild())
{
Panel* child = iter->GetValue();
if (child->GetSelect())
return child;
}
return nullptr;
}
void Panel::SetChildSelect(Panel* panel)
{
for (auto& iter : _node->GetChild())
{
Panel* child = iter->GetValue();
child->SetSelectAll(panel == child);
}
}
dl::UI::Panel* Panel::GetChildPickup()
{
for (auto& iter : _node->GetChild())
{
Panel* child = iter->GetValue();
if (child->IsPickup())
return child;
}
return nullptr;
}
RectF Panel::GetRect()
{
RectF ret{};
for (Components* cpt : _allEle)
{
Cpt::ElementData* comp = cpt->Get<Cpt::ElementData>();
if (!comp)
continue;
RectF rect = comp->GetRect();
ret[0] = std::min(ret[0], rect[0]);
ret[1] = std::min(ret[1], rect[1]);
ret[2] = std::max(ret[2], rect[2]);
ret[3] = std::max(ret[3], rect[3]);
}
for (auto& iter : _node->GetChild())
{
Panel* child = iter->GetValue();
RectF rect = child->GetRect();
ret[0] = std::min(ret[0], rect[0]);
ret[1] = std::min(ret[1], rect[1]);
ret[2] = std::max(ret[2], rect[2]);
ret[3] = std::max(ret[3], rect[3]);
}
return ret;
}
dl::Position Panel::GetParentSize()
{
auto parent = GetParent();
if (parent && parent->GetSize()!= Position{})
{
return parent->GetSize();
}
return toPosition(g_system->GetWindowSize()) / g_ui->GetScale();
}
dl::Position Panel::GetSize()
{
if (_bSizeAuto)
return _locator.GetSize();
if (_size == Position{})
{
return GetParentSize();
}
return _size;
}
void Panel::SetDir(Align::Dir4 dir)
{
_coor->SetRotate(Align::Dir2Rotate(dir));
_dir = dir;
_refresh_pos(GetParentSize());
}
}
#endif