diff --git a/src/proclamation_options_page.cpp b/src/proclamation_options_page.cpp index 07e04df..eb67da6 100644 --- a/src/proclamation_options_page.cpp +++ b/src/proclamation_options_page.cpp @@ -198,7 +198,7 @@ void ProclamationOptionsPage::rebuildItems() FlatItem::Type::SubCategory, std::to_string(sub.id), sub.name, - 1, false, false, false, + 1, true, false, false, }); for (const auto& p : proclamations_) { @@ -268,7 +268,7 @@ void ProclamationOptionsPage::rebuildVisible() parentVisible = true; // the always-on top-level proclamation } else if (currentRoot >= 0 && items_[currentRoot].expanded) { parentVisible = (item.depth == 1) || - (item.depth == 2 && currentSub >= 0 && items_[currentSub].expanded); + (item.depth == 2 && currentSub >= 0); } if (parentVisible) visible_.push_back(i); } @@ -283,7 +283,7 @@ void ProclamationOptionsPage::toggleItem() if (visible_.empty()) return; FlatItem& item = items_[visible_[highlightIndex_]]; - if (item.type == FlatItem::Type::RootCategory || item.type == FlatItem::Type::SubCategory) { + if (item.type == FlatItem::Type::RootCategory) { item.expanded = !item.expanded; rebuildVisible(); return; @@ -388,7 +388,7 @@ void ProclamationOptionsPage::collapseCurrent() { if (visible_.empty()) return; FlatItem& item = items_[visible_[highlightIndex_]]; - if (item.type == FlatItem::Type::RootCategory || item.type == FlatItem::Type::SubCategory) { + if (item.type == FlatItem::Type::RootCategory) { if (item.expanded) { item.expanded = false; rebuildVisible(); @@ -400,7 +400,7 @@ void ProclamationOptionsPage::expandCurrent() { if (visible_.empty()) return; FlatItem& item = items_[visible_[highlightIndex_]]; - if (item.type == FlatItem::Type::RootCategory || item.type == FlatItem::Type::SubCategory) { + if (item.type == FlatItem::Type::RootCategory) { if (!item.expanded) { item.expanded = true; rebuildVisible(); @@ -526,8 +526,7 @@ void ProclamationOptionsPage::handleEvent(const SDL_Event& event) if (searchActive_) return; if (!visible_.empty()) { const FlatItem& item = items_[visible_[highlightIndex_]]; - if ((item.type == FlatItem::Type::RootCategory || - item.type == FlatItem::Type::SubCategory) && item.expanded) { + if (item.type == FlatItem::Type::RootCategory && item.expanded) { collapseCurrent(); } else { moveToParent(); @@ -655,14 +654,18 @@ void ProclamationOptionsPage::render(SDL_Renderer* renderer) SDL_RenderTexture(renderer, emptyHintText_.texture, nullptr, &dst); } } else { - // Compute the widest row so the block can be centered. + // Stable width: compute from every result so the list doesn't shift. float maxTotalWidth = 0.0f; + for (const auto& r : searchResults_) { + int w = 0, h = 0; + TTF_GetStringSize(fontItem_, proclamations_[r].title.c_str(), 0, &w, &h); + maxTotalWidth = std::max(maxTotalWidth, static_cast(w)); + } + std::vector textWidths(static_cast(listSize)); for (int i = scrollOffset_; i < scrollOffset_ + visibleCount_ && i < listSize; ++i) { - const std::string& label = proclamations_[searchResults_[i]].title; int w = 0, h = 0; - TTF_GetStringSize(fontItem_, label.c_str(), 0, &w, &h); - maxTotalWidth = std::max(maxTotalWidth, static_cast(w)); + TTF_GetStringSize(fontItem_, proclamations_[searchResults_[i]].title.c_str(), 0, &w, &h); textWidths[i] = static_cast(w); } float sharedX = (fw - maxTotalWidth) / 2.0f; @@ -695,19 +698,29 @@ void ProclamationOptionsPage::render(SDL_Renderer* renderer) } } else { // --- Browse tree --- - // Compute the widest row so the block can be centered. + // Stable width: compute from every item so the list doesn't + // shift left/right when groups expand or collapse. float maxTotalWidth = 0.0f; - std::vector textWidths(visible_.size()); - for (int i = scrollOffset_; i < scrollOffset_ + visibleCount_ && i < static_cast(visible_.size()); ++i) { - const FlatItem& item = items_[visible_[i]]; + for (const auto& item : items_) { std::string label = item.label; - if (item.type == FlatItem::Type::RootCategory || item.type == FlatItem::Type::SubCategory) { + if (item.type == FlatItem::Type::RootCategory) { label = (item.expanded ? "[-] " : "[+] ") + label; } int w = 0, h = 0; TTF_GetStringSize(fontItem_, label.c_str(), 0, &w, &h); float total = item.depth * indent + static_cast(w); maxTotalWidth = std::max(maxTotalWidth, total); + } + + std::vector textWidths(visible_.size()); + for (int i = scrollOffset_; i < scrollOffset_ + visibleCount_ && i < static_cast(visible_.size()); ++i) { + const FlatItem& item = items_[visible_[i]]; + std::string label = item.label; + if (item.type == FlatItem::Type::RootCategory) { + label = (item.expanded ? "[-] " : "[+] ") + label; + } + int w = 0, h = 0; + TTF_GetStringSize(fontItem_, label.c_str(), 0, &w, &h); textWidths[i] = static_cast(w); } @@ -721,7 +734,7 @@ void ProclamationOptionsPage::render(SDL_Renderer* renderer) float y = listTop + rowIndex * rowPitch; std::string label = item.label; - if (item.type == FlatItem::Type::RootCategory || item.type == FlatItem::Type::SubCategory) { + if (item.type == FlatItem::Type::RootCategory) { label = (item.expanded ? "[-] " : "[+] ") + label; }