#include "ui/dl_ui_manager.h" #ifndef DL_DISABLE_RENDER #include "io/dl_file.h" #include "base/dl_string.h" #include "render/dl_graphics.h" #include "system/dl_system.h" namespace dl::UI { UI::Text* Manager::CreateText(std::string_view name) { auto iter = _allText.find(std::string{ name }); if (iter == _allText.end()) { log_err("UI::Text不存在,请使用Register注册:{}", name); return UI::Text::Create(g_factory->CreateTextDefault()); } return iter->second->Clone(); } gcText Manager::CreateTextOnly(std::string_view name) { auto iter = _allText.find(std::string{ name }); if (iter == _allText.end()) { log_err("UI::Text不存在,请使用Register注册:{}", name); return g_factory->CreateTextDefault(); } return g_factory->CloneText(iter->second->GetText()); } UI::ButtonSprite* Manager::CreateButtonSprite(std::string_view name) { auto iter = _allBtnSprite.find(std::string{ name }); if (iter == _allBtnSprite.end()) { log_err("ButtonSprite不存在,请使用Register注册:{}", name); return CreateButtonSpriteDefault(); } return iter->second->Clone(); } Background* Manager::CreateBackground(std::string_view name) { auto iter = _allBackground.find(std::string{ name }); if (iter == _allBackground.end()) { log_err("Background不存在,请使用Register注册:{}", name); return CreateBackgroundDefault(); } return iter->second->Clone(); } dl::Locator::SL Manager::CreateLocator(std::string_view name) { auto iter = _allLocator.find(std::string{ name }); if (iter == _allLocator.end()) { log_err("Locator不存在,请使用Register注册:{}", name); return {}; } return iter->second; } dl::UI::ListBox* Manager::CreateListBox(std::string_view name) { auto iter = _allListBox.find(std::string{ name }); if (iter == _allListBox.end()) { log_err("ListBox不存在,请使用Register注册:{}", name); return {}; } return iter->second->Clone(); } dl::UI::Text* Manager::CreateTextDefault() { return UI::Text::Create(g_factory->CreateTextDefault()); } UI::ButtonSprite* Manager::CreateButtonSpriteDefault(ButtonStyle style) { //34/55 约等于 0.618 Position size; switch (style) { case ButtonStyle::SMALL: size = Math::CreatePositionByRatioGoldW(_arrSizeType[SizeType::SMALL]); break; case ButtonStyle::NORMAL: size = Math::CreatePositionByRatioGoldW(_arrSizeType[SizeType::NORMAL]); break; case ButtonStyle::LARGE: size = Math::CreatePositionByRatioGoldW(_arrSizeType[SizeType::LARGE]); break; case ButtonStyle::BOX: size = { 30, 30 }; break; case ButtonStyle::CLOSE: size = { 24, 24 }; break; case ButtonStyle::LONG: size = { _arrSizeType[SizeType::LONG], 20 }; break; case ButtonStyle::SWITCH: size = { 18, 18 }; break; default: assert(0); break; } std::vector mul_spr; mul_spr.resize(3); for (size_t i = 0; i < 3; ++i) { mul_spr[i] = g_factory->CreateSpriteDefault(); mul_spr[i]->SetQuad(createQuad(size, false)); } // ButtonSprite* ret; if (style == ButtonStyle::SWITCH) { mul_spr[0]->SetColor(ColorDef::GRAY_DARK); mul_spr[1]->SetColor(ColorDef::WHITE); mul_spr[2]->SetColor(ColorDef::GRAY_LIGHT); ret = ButtonSprite::Create(mul_spr); ret->SetMode(ButtonMode::SWITCH); ret->AddText(g_factory->CreateTextDefault(), toVector(ColorDef::BLACK, 5), toVector(Position{40, 0}, 5)); ret->SetTextAlign(Align::LC); ret->SetCustomRender([](Button* btn) { // 描边 g_gfx->SetCoor(btn->GetCoor()); g_gfx->SetColor(ColorDef::BLACK); g_gfx->Rectangle2D({}, btn->GetSize()); g_gfx->SetOrder(btn->GetOrder(-1)); // Position size = btn->GetSize(); if (btn->IsSelect()) { g_gfx->SetColor(ColorDef::GREEN_DARK); g_gfx->StrokeLine({}, { size.w * 0.5f, size.h }, 2); g_gfx->StrokeLine({ size.w * 0.5f, size.h } ,{ size.w , 0}, 2); } else { g_gfx->SetColor(ColorDef::RED); g_gfx->StrokeLine({}, { size.w, size.h }, 2); g_gfx->StrokeLine({ size.w, 0 }, { 0 , size.h }, 2); } }); } else { mul_spr[0]->SetColor(ColorDef::GRAY_LIGHT); mul_spr[1]->SetColor(ColorDef::WHITE); mul_spr[2]->SetColor(ColorDef::GRAY); ret = ButtonSprite::Create(mul_spr); ret->AddTextDefault(); if (style != ButtonStyle::CLOSE) { ret->SetCustomRender([](Button* btn) { Position size = btn->GetSize(); // 描边 g_gfx->SetCoor(btn->GetCoor()); g_gfx->SetColor(ColorDef::BLACK); g_gfx->SetOrder(btn->GetOrder(-1)); g_gfx->Rectangle2D({}, size); // 投影 if (!btn->IsDown()) { g_gfx->SetOrder(btn->GetOrder(0)); g_gfx->Line2D({ size.w + 1, 0 }, { size.w + 1, size.h + 1 }); g_gfx->Line2D({ 1, size.h + 1 }, { size.w + 1, size.h + 1 }); } else { g_gfx->Line2D({ 1, 1 }, { size.w, 1 }); g_gfx->Line2D({ 1, 1 }, { 1, size.h }); } }); } else { ret->SetCustomRender([](Button* btn) { Position size = btn->GetSize(); // 描边 g_gfx->SetCoor(btn->GetCoor()); g_gfx->SetColor(ColorDef::BLACK); g_gfx->SetOrder(btn->GetOrder(-1)); g_gfx->Rectangle2D({}, size); // 投影 if (!btn->IsDown()) { g_gfx->SetOrder(btn->GetOrder(0)); g_gfx->Line2D({ size.w + 1, 0 }, { size.w + 1, size.h + 1 }); g_gfx->Line2D({ 1, size.h + 1 }, { size.w + 1, size.h + 1 }); } // 叉 g_gfx->SetOrder(btn->GetOrder(-1)); g_gfx->SetColor(ColorDef::GRAY_DARK); g_gfx->StrokeLine( { size.w * 0.25f, size.h * 0.25f }, { size.w * 0.75f, size.h * 0.75f }, 2); g_gfx->StrokeLine( { size.w * 0.75f, size.h * 0.25f }, { size.w * 0.25f , size.h * 0.75f }, 2); }); } } return ret; } Background* Manager::CreateBackgroundDefault() { Background* ret = Background::Create(); gcSprite spr = g_factory->CreateSpriteDefault(); spr->SetColor(ColorDef::GRAY); ret->Set(spr); ret->SetCustomRender([](Background* bg) { Position size = bg->GetSize(); // 描边 g_gfx->SetCoor(bg->GetCoor()); g_gfx->SetColor(ColorDef::GREEN); g_gfx->SetOrder(bg->GetOrder(-1)); g_gfx->Rectangle2D({}, size); // 投影 if (true) { g_gfx->SetColor(createColor(ColorDef::BLACK, 0.5f)); g_gfx->SetOrder(bg->GetOrder(0)); g_gfx->Line2D({ size.w + 1, 0 }, { size.w + 1, size.h + 1 }); g_gfx->Line2D({ 1, size.h + 1 }, { size.w + 1, size.h + 1 }); } }); return ret; } ListBox* Manager::CreateListBoxDefault(bool add_text) { // item Panel* item = g_ui->CreatePanel(); item->SetLocator(createLocatorZero()); { ButtonSprite* btn = g_ui->CreateButtonSpriteDefault(); btn->SetMode(ButtonMode::RADIO); btn->SetSpriteQuad(ButtonState::MAX_NUM, createQuad( Size{ (unsigned)_arrSizeType[SizeType::LONG], 16 }, false)); btn->SetSpriteColor(ButtonState::NORMAL, ColorDef::WHITE); btn->SetSpriteColor(ButtonState::OVER, ColorDef::GREEN); btn->SetSpriteColor(ButtonState::DOWN, ColorDef::BLUE); if (add_text) btn->AddTextDefault(); item->Add(btn); item->SetSize(btn->GetSize()); } ListBox* ret = ListBox::Create(item, 10); ret->SetItemLocator(createLocatorY(16.0f)); return ret; } dl::UI::EditBox* Manager::CreateEditBoxDefault(bool single_line) { // item Panel* panel = g_ui->CreatePanel(); panel->SetLocator(createLocatorZero()); ButtonSprite* btn = g_ui->CreateButtonSpriteDefault(); btn->SetMode(ButtonMode::RADIO); if (single_line) btn->SetSpriteQuad(ButtonState::MAX_NUM, createQuad( Size{ (unsigned)_arrSizeType[SizeType::LONG], 16 }, false)); else btn->SetSpriteQuad(ButtonState::MAX_NUM, createQuad( Size{ (unsigned)_arrSizeType[SizeType::LONG], 120 }, false)); btn->SetSpriteColor(ButtonState::NORMAL, ColorDef::WHITE); btn->SetSpriteColor(ButtonState::OVER, ColorDef::GREEN); btn->SetSpriteColor(ButtonState::DOWN, ColorDef::BLUE); panel->Add(btn); EditBox* ret = EditBox::Create(panel, g_factory->CreateTextDefault()); ret->SetSingleLine(single_line); ret->SetColor({ ColorDef::RED, ColorDef::RED, ColorDef::WHITE }); // 多行输入框自动换行 if (!single_line) { ret->GetText()->SetMaxW(btn->GetSize()[0]); } return ret; } dl::UI::Tree* Manager::CreateTreeDefault() { // item Panel* panel = g_ui->CreatePanel(); panel->SetLocator(createLocatorZero()); { ButtonSprite* btn = g_ui->CreateButtonSpriteDefault(); btn->SetMode(ButtonMode::SWITCH); btn->SetSpriteQuad(ButtonState::MAX_NUM, createQuad(Size{ 64, 20 }, false)); btn->SetSpriteColor(ButtonState::NORMAL, ColorDef::WHITE); btn->SetSpriteColor(ButtonState::OVER, ColorDef::GREEN); btn->SetSpriteColor(ButtonState::DOWN, ColorDef::BLUE); panel->Add(btn); } Tree* ret = Tree::Create(panel); ret->SetCallbackSetPosition([](UI::Panel* panel, size_t i, size_t extra) { panel->SetPosPixel(Position{ 32.0f, (i + extra) * 20.0f }); }); return ret; } Menu* Manager::CreateMenuDefault() { Background* bg = g_ui->CreateBackgroundDefault(); Background* bg_combo = g_ui->CreateBackgroundDefault(); Panel* panel_menu = g_ui->CreatePanel(); panel_menu->SetLocator(createLocatorZero()); { UI::Text* txt = g_ui->CreateTextDefault(); panel_menu->Add(txt); } Panel* panel_btn = g_ui->CreatePanel(); panel_btn->SetLocator(createLocatorZero()); { UI::Text* txt = g_ui->CreateTextDefault(); panel_btn->Add(txt); UI::Text* txt_hotkey = g_ui->CreateTextDefault(); panel_btn->Add(txt_hotkey); } Menu* ret = Menu::Create( bg, panel_menu, createLocatorX(40, 0, 32) , bg_combo, panel_btn, createLocatorY(30, 0, 30)); return ret; } ProgressBar* Manager::CreateProgressBarDefault() { Background* bg = g_ui->CreateBackgroundDefault(); bg->SetSize({ 200, 24 }); bg->SetColor(ColorDef::WHITE); Background* bg_mid = Background::Create(); bg_mid->Set(g_factory->CreateSpriteDefault(ColorDef::GRAY)); //Background* bg_front = g_ui->CreateBackgroundDefault(); Text* txt = g_ui->CreateTextDefault(); txt->GetText()->SetColor(ColorDef::GREEN); txt->GetText()->SetOutline(1, ColorDef::BLACK); ProgressBar* ret = ProgressBar::Create(bg, bg_mid, txt); ret->SetMidRect({ 1, 1, 199, 23 }); return ret; } void Manager::Register(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::ParseFile(json_path); if (j.is_null()) return; RegKey key; //类型名字检查 std::string type; Json::Get(j, "type", type); if (type.empty()) { log_err0("必须含有type字段!例如text"); return; } Json::Get(j, "name", key._name); if (key._name.empty()) { log_err0("必须含有name字段!例如normal"); return; } key._type = String2ElementType(type); if (key._type == ElementType::UNKNOWN) return; key._json = j; _allReg.push_back(key); } void Manager::_reg_background(json& j, const std::string& name) { if (_allBackground.contains(name)) { log_err("name错误(不能为空,或重复):{}", name); return; } Background* bg = nullptr; std::string spr; std::string spr9; Json::DisableLog l; Json::Get(j, "spr", spr); Json::Get(j, "spr9", spr9); if (!spr.empty()) { gcSprite p_spr = g_factory->CreateSprite(spr); bg = Background::Create(); bg->Set(p_spr); } else if (!spr9.empty()) { Sprite9* p_spr9 = Sprite9::Create(spr9); bg = Background::Create(); bg->Set(p_spr9); } if (bg) { /*Point extra; if (Json::Get(j, "extra", extra)) bg->SetExtra(extra); Point offset; if (Json::Get(j, "offset", offset)) bg->SetOffset(offset);*/ _allBackground[name] = bg; log_msg("成功注册一个Background:{}", name); } else { log_msg("没有有效的字段:{}(spr、spr9)", name); } } void Manager::_reg_text(json& j, const std::string& name) { if (_allText.contains(name)) { log_err("name错误(不能为空,或重复):{}", name); return; } std::string color; std::string color_o; std::string color_s; std::string anchor; size_t id; unsigned size; unsigned size_o = 0; unsigned size_s = 0; std::string str; std::optional opt_color; std::optional opt_color_o; std::optional opt_color_s; Align::Direction2 hv; //id、大小、颜色 Json::Get(j, "id", id); if (id >= g_factory->GetFontSize()) { log_err("id越界:{}", id); return; } Json::Get(j, "size", size); Json::DisableLog l; Json::Get(j, "string", str); // 大小 Json::Get(j, "size_o", size_o); Json::Get(j, "size_s", size_s); // 颜色 if (Json::Get(j, "color", color)) opt_color = g_factory->GetColorCheck(color); if (Json::Get(j, "color_o", color_o)) opt_color_o = g_factory->GetColorCheck(color_o); if (Json::Get(j, "color_s", color_s)) opt_color_s = g_factory->GetColorCheck(color_s); // 对齐 if (Json::Get(j, "anchor", anchor)) { hv = Align::Anchor2Direction(anchor); } gcText txt = g_factory->CreateText(id, size); txt->SetOutline(size_o); txt->SetShadow(size_s); if (opt_color.has_value()) txt->SetColor(opt_color.value()); if (opt_color_o.has_value()) txt->SetColor(opt_color_o.value(), TextParam::OUTLINE); if (opt_color_s.has_value()) txt->SetColor(opt_color_s.value(), TextParam::SHADOW); txt->SetString(str); UI::Text* ret = UI::Text::Create(txt); ret->SetElementData(hv); _allText[name] = ret; log_msg("成功注册一个Text:{}", name); } void Manager::_reg_button(json& j, const std::string& name) { if (_allBtnSprite.contains(name)) { log_err("name错误(不能为空,或重复):{}", name); return; } std::string style; std::string mode; std::string spr; std::string txt; Json::Get(j, "style", style); Json::DisableLog l; Json::Get(j, "mode", mode); Json::Get(j, "spr", spr); Json::Get(j, "txt", txt); if (style == "sprite") { std::vector mul_spr = g_factory->CreateSpriteMulti(spr); ButtonSprite* btn = ButtonSprite::Create(mul_spr); if (!txt.empty()) { gcText p_txt = CreateTextOnly(txt); btn->AddText(p_txt, {}, {}); } //mode if (mode == "switch") btn->SetMode(UI::Button::Mode::SWITCH); else if (mode == "radio") btn->SetMode(UI::Button::Mode::RADIO); _allBtnSprite[name] = btn; log_msg("成功注册一个ButtonSprite:{}", name); } else { log_msg("style未知:{}", style); return; } } void Manager::_reg_msg_box(json& j, const std::string& name) {/* if (_allMsgBox.contains(name)) { log_err("name错误(不能为空,或重复):{}", name); return; } std::string bg; std::string txtTitle; std::string txt; std::string btn; std::string btnClose; Float dxBtn; Json::Get(j, "bg", bg); Json::Get(j, "txt_title", txtTitle); Json::Get(j, "txt", txt); Json::Get(j, "btn", btn); Json::Get(j, "btn_close", btnClose); Json::Get(j, "dx_btn", dxBtn); Background* p_bg = CreateBackground(bg); MsgBox* msg_box = MsgBox::Create( p_bg, CreateTextOnly(txtTitle), CreateTextOnly(txt), CreateButtonSprite(btn), CreateButtonSprite(btnClose), dxBtn); _allMsgBox[name] = msg_box; log_msg("成功注册一个MsgBox:{}", name);*/ } void Manager::_reg_locator(json& j, std::string_view name) { if (_allLocator.contains(std::string{ name })) { log_err("name错误(不能为空,或重复):{}", name); return; } Locator::SL loc; std::string layout; Json::DisableLog l; Json::Get(j, "dt", loc._dt); if (Json::Get(j, "layout", layout)) loc._layout = String2Layout(layout); Json::Get(j, "num", loc._num); Json::Get(j, "start", loc._start); _allLocator[std::string{ name }] = loc; log_msg("成功注册一个Locator:{}", name); } void Manager::_reg_list_box(json& j, std::string_view name) { if (_allListBox.contains(std::string{ name })) { log_err("name错误(不能为空,或重复):{}", name); return; } std::string btn_name; std::string txt_name; size_t num = 10; Float dy = 32.0_f; Float scroll_k = 1.0_f; Json::Get(j, "btn", btn_name); Json::DisableLog l; Json::Get(j, "text", txt_name); Json::Get(j, "num", num); Json::Get(j, "dy", dy); Json::Get(j, "scroll_k", scroll_k); ButtonSprite* btn = CreateButtonSprite(btn_name); if (!txt_name.empty()) { // todo 颜色 btn->AddText(CreateTextOnly(txt_name), { ColorDef::WHITE, ColorDef::WHITE, ColorDef::GREEN }, { {}, {0, -1}, {0, 1} }); } Panel* item = CreatePanel(); item->SetLocator(createLocatorZero()); item->Add(btn); item->SetSize(btn->GetSize()); ListBox* list_box = ListBox::Create(item, num); list_box->SetScrollK(scroll_k); _allListBox[std::string{ name }] = list_box; log_msg("成功注册一个ListBox:{}", name); } void Manager::RegisterEnd() { _allReg.sort(); for (RegKey& key : _allReg) { json& j = key._json; switch (key._type) { case ElementType::BACKGROUND: _reg_background(j, key._name); break; case ElementType::TEXT: _reg_text(j, key._name); break; case ElementType::BUTTON: _reg_button(j, key._name); break; case ElementType::MSG_BOX: _reg_msg_box(j, key._name); break; case ElementType::LOCATOR: _reg_locator(j, key._name); break; case ElementType::LIST_BOX: _reg_list_box(j, key._name); break; default: assert(0); break; } } } void Manager::RegisterAll(std::string_view path) { std::vector all_file; File::GetPathFileAll(path, all_file, ".json"); for (auto& iter : all_file) { Register(iter); } RegisterEnd(); } void Manager::_resize() { // 窗口大小为0,可能是最小化 if (Any::Zero(g_system->GetWindowSize())) return; // 更新ui缩放(未设置则不缩放) _refresh_standard_size(); _resize_panel_root(); // 更新panel大小,和元素定位 auto fn = [&](Panel* p) { p->_refresh_size(); }; _allPanel.ForEach(fn); // 根面板的所有子面板更新位置 for (auto* node : _panelRoot->_node->GetChild()) { Panel* panel = node->GetValue(); if(panel->_bAutoCoor) panel->_refresh_pos(_panelRoot->GetSize()); } } void Manager::_update_pre() { _bDebug = false; _bHide = false; for (auto& node : _allPanel) { node->GetValue()->_bUpdate = false; node->GetValue()->_bRender = false; } } void Manager::_update() { _update_window(); _panelRoot->Update(); } void Manager::_render() { _panelRoot->Render(); if (_bDebug) _debug_render(); } void Manager::_resize_panel_root() { // 需要拉伸填充 Size size = g_system->GetWindowSize(); _panelRoot->SetSize(toPosition(size) / _uiScale); } void Manager::_refresh_standard_size() { if (Any::Zero(_sizeStandard)) return; Position k = toPosition(g_system->GetWindowSize()) / toPosition(_sizeStandard); Float s = Select::Min(k); if (s < 0.1f) s = 0.1f; SetScale(s); } void Manager::RenderDebug() { _bDebug = true; } void Manager::_debug_render() { if (!_bDebug) return; for (auto& node : _allPanel) { Panel* panel = node->GetValue(); if (!panel->IsUpdate()) continue; // 绘制:panel坐标 g_gfx->RenderCoor(panel->_coor, panel->GetParent() != _panelRoot); // 绘制:panel大小 /*g_gfx->SetCoor(panel->_coor); g_gfx->SetColor(createColorRandom(0.1f)); g_gfx->RectangleSolid2D({}, panel->GetSize());*/ //组件处理 for (Components* cpts : panel->_allEle) { Cpt::GetCoor* comp_coor = cpts->Get(); Coor* coor = comp_coor ? comp_coor->Call() : nullptr; if (coor) { if (Cpt::IsPickup* comp = cpts->Get()) { if (comp->Call()) { // 绘制:拾取到的组件坐标 g_gfx->RenderCoor(coor); } } // 绘制:组件大小 if (Cpt::ElementData* comp = cpts->Get()) { RenderDebugElementData(coor, *comp); } } // 绘制:组件自定义绘制 if (Cpt::RenderDebug* comp = cpts->Get()) { comp->Call(); } } } Button* btn = Button::GetClickControl(); if (btn) { gcText txt = g_factory->RenderText(); txt->GetCoor()->SetParent(btn->GetCoor()); txt->SetString("当前锁定"); } } void Manager::_on_char(char32_t ch) { if (!_edtFocus) return; _edtFocus->_on_char(ch); } void Manager::_on_key(int action, bool ctrl) { if (!_edtFocus) return; KeyCode act = (KeyCode)action; if (ctrl) { if (act == KeyCode::X) { g_system->SetClipboardString(_edtFocus->GetStringSelect()); _edtFocus->DeleteSelect(); } else if (act == KeyCode::C) g_system->SetClipboardString(_edtFocus->GetStringSelect()); else if (act == KeyCode::V) _edtFocus->_on_string(g_system->GetClipboardString()); else if (act == KeyCode::A) _edtFocus->_on_select_all(); } else { if (act == KeyCode::BACKSPACE) _edtFocus->_on_backspace(); else if (act == KeyCode::DELETE) _edtFocus->_on_delete(); else if (act == KeyCode::LEFT) _edtFocus->_on_left(); else if (act == KeyCode::RIGHT) _edtFocus->_on_right(); else if (act == KeyCode::ENTER || act == KeyCode::KP_ENTER) _edtFocus->_on_enter(); } } void Manager::SetFocusEditBox(EditBox* edt, bool focus /*= true*/) { if (focus) { if (_edtFocus == edt) return; // 前一个输入框,设为非激活 if(_edtFocus) _edtFocus->_on_focus(false); edt->_on_focus(true); _edtFocus = edt; } else { if (_edtFocus == edt) { edt->_on_focus(false); _edtFocus = nullptr; } } } void Manager::RenderDebugElementData(Coor* coor, const Cpt::ElementData& elem_data) { //Position p0 = coor->GetPosition() - elem_data.GetAnchor(); //Position p1 = p0 + elem_data.GetSize(); //g_gfx->SetCoor(coor->GetParent()); //g_gfx->SetColor(createColor(ColorDef::PURPLE, 1.0f)); //g_gfx->Rectangle2D(p0, p1); /*Position p0 = coor->GetPosition(); Position p1 = p0 + elem_data.GetSize(); g_gfx->SetCoor(coor->GetParent()); g_gfx->SetColor(createColor(ColorDef::PURPLE, 1.0f)); g_gfx->Rectangle2D(p0, p1);*/ Position p0 = {}; Position p1 = elem_data.GetSize(); g_gfx->SetCoor(coor); g_gfx->SetColor(createColor(ColorDef::PURPLE, 1.0f)); g_gfx->Rectangle2D(p0, p1); } Size Manager::GetStandardSize() { return Any::Zero(_sizeStandard) ? g_system->GetWindowSize() : _sizeStandard; } void Manager::SetStandardSize(const Size& size) { if (!g_system->IsWindowExist()) { log_err("必须创建窗口之后调用!"); return; } _sizeStandard = size; _refresh_standard_size(); } void Manager::AddWindow(std::string_view name, Window* win) { Window*& win_old = _allWindow[std::string{ name }]; if (win_old) { auto iter = std::find(_listShowWindow.begin(), _listShowWindow.end(), win_old); if (iter != _listShowWindow.end()) { _listShowWindow.erase(iter); } delete win_old; log_info("已释放旧的同名窗口:{}", name); } win_old = win; win->_bInManager = true; win->_name = name; _on_window_show_change(win, win->IsVisible()); } Window* Manager::GetWindow(std::string_view name) { auto iter = _allWindow.find(std::string{ name }); if (iter == _allWindow.end()) { log_warn("查找窗口失败:{}", name); return nullptr; } return iter->second; } void Manager::_update_window() { // 防止遍历时删除自身 std::list list_temp = _listShowWindow; for (auto& iter : list_temp) { iter->Update(); } } void Manager::ShowWindow(Window* win, WindowShowMode mode /*= WindowShowMode::SHOW*/) { bool visible_old = win->IsVisible(); bool visible_new; switch (mode) { case WindowShowMode::SHOW: visible_new = true; break; case WindowShowMode::HIDE: visible_new = false; break; case WindowShowMode::TOGGLE: visible_new = !visible_old; break; default: assert(0); visible_new = true; break; } if (visible_old != visible_new) { win->SetVisible(visible_new); } } void Manager::ShowWindow(std::string_view name, WindowShowMode mode /*= WindowShowMode::SHOW*/) { Window* win = GetWindow(name); if (!win) return; ShowWindow(win, mode); } void Manager::SetWindowTop(Window* win) { auto iter = std::find(_listShowWindow.begin(), _listShowWindow.end(), win); if (iter == _listShowWindow.end()) { log_warn("仅添加到管理器内调用有效!"); return; } // 只有自己一个,不处理 if (_listShowWindow.back() == win) return; _listShowWindow.erase(iter); // 插入尾部 float order_min = _listShowWindow.back()->GetOrder(); if (order_min <= _orderMin) {// 尾部已经即将超出范围,则重排order _listShowWindow.push_back(win); _refresh_window_order(); } else { win->SetOrder(Math::OffsetOrder(order_min, -1)); _listShowWindow.push_back(win); } } void Manager::_on_window_show_change(Window* win, bool visible) { if (visible) { if (_listShowWindow.empty()) {// 空列表直接插入 win->SetOrder(_orderMax); _listShowWindow.push_back(win); } else { // 只有自己一个,不处理 if (_listShowWindow.back() == win) return; // 已存在则移除 auto iter = std::find(_listShowWindow.begin(), _listShowWindow.end(), win); if(iter != _listShowWindow.end()) _listShowWindow.erase(iter); // 插入尾部 float order_min = _listShowWindow.back()->GetOrder(); if (order_min <= _orderMin) {// 尾部已经即将超出范围,则重排order _listShowWindow.push_back(win); _refresh_window_order(); } else { win->SetOrder(Math::OffsetOrder(order_min, -1)); _listShowWindow.push_back(win); } } } else { auto iter = std::find(_listShowWindow.begin(), _listShowWindow.end(), win); if (iter != _listShowWindow.end()) { _listShowWindow.erase(iter); } } } void Manager::_refresh_window_order() { float order = _orderMax; for (auto& iter : _listShowWindow) { iter->SetOrder(order); order = Math::OffsetOrder(order, -1); } } void Manager::_release_window(Window* win) { if (!win->_bInManager) return; auto iter = _allWindow.find(win->_name); if (iter != _allWindow.end()) { _on_window_show_change(win, false); _allWindow.erase(iter); } } Manager::~Manager() { _release(); for (auto& node : _allPanel) { delete node->GetValue(); } } void Manager::_release_window_all() { auto temp = _allWindow; for (auto& iter : temp) { delete iter.second; } } } #endif