fix(ui): notification popup horizontal oscillation
Tamano FIJO del popup (Always + SizeConstraints) y flags NoResize/NoMove para evitar feedback loop entre auto-resize del popup y TextWrapped/SameLine internos. Reemplaza GetWindowContentRegionMax() por offsets explicitos calculados a partir del ancho fijo, ya que ese valor fluctua frame a frame con padding/borders y provocaba el ensanche/encogido continuo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -235,13 +235,23 @@ void toast_inbox_button(const char* id) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(spacing::sm, spacing::sm));
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(360.0f, 0.0f), ImGuiCond_Appearing);
|
||||
if (ImGui::BeginPopup(popup_id)) {
|
||||
// Header
|
||||
// Tamano FIJO del popup (Always + SizeConstraints) para evitar feedback
|
||||
// loop entre auto-resize del popup y TextWrapped/SameLine internos.
|
||||
constexpr float kInboxW = 360.0f;
|
||||
constexpr float kInboxH = 380.0f;
|
||||
ImGui::SetNextWindowSize(ImVec2(kInboxW, kInboxH), ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(kInboxW, kInboxH),
|
||||
ImVec2(kInboxW, kInboxH));
|
||||
if (ImGui::BeginPopup(popup_id, ImGuiWindowFlags_NoResize
|
||||
| ImGuiWindowFlags_NoMove)) {
|
||||
// Header — usar offset desde la izquierda calculado a partir del ancho
|
||||
// FIJO del popup, NO de GetWindowContentRegionMax() (que cambia frame
|
||||
// a frame con padding y provoca oscilacion horizontal).
|
||||
const float content_w = kInboxW - 2.0f * spacing::sm;
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, colors::text_muted);
|
||||
ImGui::TextUnformatted("Notifications");
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::SameLine(ImGui::GetWindowContentRegionMax().x - 50.0f);
|
||||
ImGui::SameLine(content_w - 50.0f);
|
||||
if (ImGui::SmallButton("Clear")) {
|
||||
toast_history_clear();
|
||||
snapshot.clear();
|
||||
@@ -254,7 +264,10 @@ void toast_inbox_button(const char* id) {
|
||||
ImGui::PopStyleColor();
|
||||
} else {
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
ImGui::BeginChild("##inbox_list", ImVec2(0, 320.0f));
|
||||
// Reservar el espacio restante para la lista — alto fijo evita
|
||||
// oscilacion vertical del popup.
|
||||
ImGui::BeginChild("##inbox_list", ImVec2(content_w, 0.0f));
|
||||
const float list_w = ImGui::GetContentRegionAvail().x;
|
||||
// Mostrar mas reciente arriba
|
||||
for (auto it = snapshot.rbegin(); it != snapshot.rend(); ++it) {
|
||||
const auto& t = *it;
|
||||
@@ -262,9 +275,14 @@ void toast_inbox_button(const char* id) {
|
||||
ImGui::TextUnformatted(glyph_for(t.kind));
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::SameLine();
|
||||
ImGui::TextWrapped("%s", t.text.c_str());
|
||||
// Wrap manual hasta x = list_w - 30 (espacio para el age),
|
||||
// usando coordenadas del cursor relativas al window.
|
||||
const float wrap_x = ImGui::GetCursorPosX() + (list_w - ImGui::GetCursorPosX()) - 36.0f;
|
||||
ImGui::PushTextWrapPos(wrap_x);
|
||||
ImGui::TextUnformatted(t.text.c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, colors::text_dim);
|
||||
ImGui::SameLine(ImGui::GetWindowContentRegionMax().x - 30.0f);
|
||||
ImGui::SameLine(list_w - 30.0f);
|
||||
ImGui::TextUnformatted(format_age(t.created, now).c_str());
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::Separator();
|
||||
|
||||
Reference in New Issue
Block a user