#include "TabControl.h" inline void TabControl::initTabBar() { if (controls.empty())return; int butW = max(this->width / (int)controls.size(), BUTMINWIDTH); int butH = max(this->height / (int)controls.size(), BUTMINHEIGHT); if (this->tabPlacement == StellarX::TabPlacement::Top || this->tabPlacement == StellarX::TabPlacement::Bottom) for (auto& c : controls) { c.first->setHeight(tabBarHeight); c.first->setWidth(butW); } else if (this->tabPlacement == StellarX::TabPlacement::Left || this->tabPlacement == StellarX::TabPlacement::Right) for (auto& c : controls) { c.first->setHeight(butH); c.first->setWidth(tabBarHeight); } int i = 0; switch (this->tabPlacement) { case StellarX::TabPlacement::Top: for (auto& c : controls) { c.first->setX(this->x + i * butW); c.first->setY(this->y); i++; } break; case StellarX::TabPlacement::Bottom: for (auto& c : controls) { c.first->setX(this->x + i * butW); c.first->setY(this->y+this->height - tabBarHeight); i++; } break; case StellarX::TabPlacement::Left: for (auto& c : controls) { c.first->setX(this->x); c.first->setY(this->y+i* butH); i++; } break; case StellarX::TabPlacement::Right: for (auto& c : controls) { c.first->setX(this->x+this->width - tabBarHeight); c.first->setY(this->y + i * butH); i++; } break; default: break; } } inline void TabControl::initTabPage() { if (controls.empty())return; //子控件坐标原点 int nX = 0; int nY = 0; switch (this->tabPlacement) { case StellarX::TabPlacement::Top: for (auto& c : controls) { c.second->setX(this->x); c.second->setY(this->y + tabBarHeight); c.second->setWidth(this->width); c.second->setHeight(this->height - tabBarHeight); } nX = this->x; nY = this->y + tabBarHeight; for (auto& c : controls) { for (auto& v : c.second->getControls()) { v->setX(v->getLocalX() + nX); v->setY(v->getLocalY() + nY); } } break; case StellarX::TabPlacement::Bottom: for (auto& c : controls) { c.second->setX(this->x); c.second->setY(this->y); c.second->setWidth(this->width); c.second->setHeight(this->height - tabBarHeight); } nX = this->x; nY = this->y; for (auto& c : controls) { for (auto& v : c.second->getControls()) { v->setX(v->getLocalX() + nX); v->setY(v->getLocalY() + nY); } } break; case StellarX::TabPlacement::Left: for (auto& c : controls) { c.second->setX(this->x + tabBarHeight); c.second->setY(this->y); c.second->setWidth(this->width - tabBarHeight); c.second->setHeight(this->height); } nX = this->x + tabBarHeight; nY = this->y; for (auto& c : controls) { for (auto& v : c.second->getControls()) { v->setX(v->getLocalX() + nX); v->setY(v->getLocalY() + nY); } } break; case StellarX::TabPlacement::Right: for (auto& c : controls) { c.second->setX(this->x); c.second->setY(this->y); c.second->setWidth(this->width - tabBarHeight); c.second->setHeight(this->height); } nX = this->x; nY = this->y; for (auto& c : controls) { for (auto& v : c.second->getControls()) { v->setX(v->getLocalX() + nX); v->setY(v->getLocalY() + nY); } } break; default: break; } } TabControl::TabControl():Canvas() { this->id = "TabControl"; } TabControl::TabControl(int x, int y, int width, int height) : Canvas(x, y, width, height) { this->id = "TabControl"; } TabControl::~TabControl() { } void TabControl::setX(int x) { this->x = x; initTabBar(); initTabPage(); dirty = true; for (auto& c : controls) { c.first->onWindowResize(); c.second->onWindowResize(); } } void TabControl::setY(int y) { this->y = y; initTabBar(); initTabPage(); dirty = true; for (auto& c : controls) { c.first->onWindowResize(); c.second->onWindowResize(); } } void TabControl::draw() { if (!dirty || !show)return; // // 在绘制 TabControl 之前,先恢复并更新背景快照: //int margin = canvaslinewidth > 1 ? canvaslinewidth : 1; //if (hasSnap) //{ // // 恢复旧快照,清除上一次绘制 // restBackground(); // // 如果位置或尺寸变了,或没有有效缓存,则重新抓取 // if (!saveBkImage || saveBkX != this->x - margin || saveBkY != this->y - margin || saveWidth != this->width + margin * 2 || saveHeight != this->height + margin * 2) // { // discardBackground(); // saveBackground(this->x - margin, this->y - margin, this->width + margin * 2, this->height + margin * 2); // } //} //else //{ // // 首次绘制或没有快照时直接抓取背景 // saveBackground(this->x - margin, this->y - margin, this->width + margin * 2, this->height + margin * 2); //} // // 再次恢复最新背景,保证绘制区域干净 // restBackground(); // 绘制画布背景和基本形状及其子画布控件 Canvas::draw(); for (auto& c : controls) { c.first->setDirty(true); c.first->draw(); } for (auto& c : controls) { c.second->setDirty(true); c.second->draw(); } dirty = false; } bool TabControl::handleEvent(const ExMessage& msg) { if (!show)return false; bool consume = false; for (auto& c : controls) if (c.first->handleEvent(msg)) { consume = true; break; } for (auto& c : controls) if(c.second->IsVisible()) if (c.second->handleEvent(msg)) { consume = true; break; } if (dirty) requestRepaint(parent); return consume; } void TabControl::add(std::pair, std::unique_ptr>&& control) { controls.push_back(std::move(control)); initTabBar(); initTabPage(); size_t idx = controls.size() - 1; controls[idx].first->setParent(this); controls[idx].first->enableTooltip(true); controls[idx].first->setbuttonMode(StellarX::ButtonMode::TOGGLE); controls[idx].first->setOnToggleOnListener([this,idx]() { controls[idx].second->setIsVisible(true); controls[idx].second->onWindowResize(); for (auto& tab : controls) { if (tab.first->getButtonText() != controls[idx].first->getButtonText()) { tab.first->setButtonClick(false); tab.second->setIsVisible(false); } } dirty = true; }); controls[idx].first->setOnToggleOffListener([this,idx]() { controls[idx].second->setIsVisible(false); dirty = true; }); controls[idx].second->setParent(this); controls[idx].second->setLinewidth(canvaslinewidth); controls[idx].second->setIsVisible(false); } void TabControl::add(std::string tabText, std::unique_ptr control) { control->setDirty(true); for (auto& tab : controls) { if (tab.first->getButtonText() == tabText) { control->setParent(tab.second.get()); control->setIsVisible( tab.second->IsVisible()); tab.second->addControl(std::move(control)); break; } } } void TabControl::setTabPlacement(StellarX::TabPlacement placement) { this->tabPlacement = placement; setDirty(true); initTabBar(); initTabPage(); } void TabControl::setTabBarHeight(int height) { tabBarHeight = height; setDirty(true); initTabBar(); initTabPage(); } void TabControl::setIsVisible(bool visible) { // 先让基类 Canvas 处理自己的回贴/丢快照逻辑 Canvas::setIsVisible(visible); // <--- 新增 this->show = visible; for (auto& tab : controls) { tab.first->setIsVisible(visible); //页也要跟着关/开,否则它们会保留旧的 saveBkImage tab.second->setIsVisible(visible); tab.second->setDirty(true); } } void TabControl::onWindowResize() { // 调用基类的窗口变化处理,丢弃快照并标记脏 Control::onWindowResize(); // 根据当前 TabControl 的新尺寸重新计算页签栏和页面区域 initTabBar(); initTabPage(); // 转发窗口尺寸变化给所有页签按钮和页面 for (auto& c : controls) { c.first->onWindowResize(); c.second->onWindowResize(); } // 尺寸变化后需要重绘自身 dirty = true; } int TabControl::getActiveIndex() const { int idx = -1; for (auto& c : controls) { idx++; if (c.first->isClicked()) return idx; } return idx; } void TabControl::setActiveIndex(int idx) { if (idx < 0 || idx > controls.size() - 1) return; if (controls[idx].first->getButtonMode() == StellarX::ButtonMode::DISABLED)return; if (controls[idx].first->isClicked()) { if (controls[idx].second->IsVisible()) return; else controls[idx].second->setIsVisible(true); } else { controls[idx].first->setButtonClick(true); } } int TabControl::count() const { return (int)controls.size(); } int TabControl::indexOf(const std::string& tabText) const { int idx = -1; for(auto& c : controls) { idx++; if (c.first->getButtonText() == tabText) return idx; } return idx; } void TabControl::setDirty(bool dirty) { this->dirty = dirty; for (auto& c : controls) { c.first->setDirty(dirty); c.second->setDirty(dirty); } } void TabControl::requestRepaint(Control* parent) { if (this == parent) { for (auto& control : controls) { if (control.first->isDirty() && control.first->IsVisible()) control.first->draw(); else if (control.second->isDirty()&&control.second->IsVisible()) control.second->draw(); } } else onRequestRepaintAsRoot(); }