58 float ttl_seconds = 3.0f, std::string action_label = {},
59 std::function<void()> on_action =
nullptr) {
61 const auto now =
now_();
73 toasts_.push_back({message, type, ttl_seconds, std::move(action_label),
74 std::move(on_action), now});
77 NotificationEntry entry;
78 entry.message = message;
80 entry.timestamp = std::chrono::system_clock::now();
107 ImGuiIO& io = ImGui::GetIO();
109 const auto now =
now_();
112 ImVec2 pos(io.DisplaySize.x - 16.f, 48.f);
130 text_color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
135 text_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
140 text_color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
144 ImGui::SetNextWindowBgAlpha(bg.w);
145 ImGui::SetNextWindowPos(pos, ImGuiCond_Always, ImVec2(1.f, 0.f));
146 ImGuiWindowFlags flags =
147 ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
148 ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNav |
149 ImGuiWindowFlags_NoFocusOnAppearing;
152 {{ImGuiCol_WindowBg, bg}, {ImGuiCol_Text, text_color}});
154 {{ImGuiStyleVar_WindowRounding, 6.0f},
155 {ImGuiStyleVar_WindowPadding, ImVec2(12.0f, 8.0f)}});
158 char window_name[32];
159 snprintf(window_name,
sizeof(window_name),
"##toast_%p", (
void*)&t);
161 bool action_clicked =
false;
162 bool hovered =
false;
163 float toast_height = 0.0f;
164 if (ImGui::Begin(window_name,
nullptr, flags)) {
167 const float max_width = std::min(360.f, io.DisplaySize.x * 0.4f);
168 ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + max_width);
169 ImGui::TextUnformatted(t.
message.c_str());
170 ImGui::PopTextWrapPos();
174 action_clicked =
true;
177 hovered = ImGui::IsWindowHovered();
178 toast_height = ImGui::GetWindowSize().y;
182 if (action_clicked) {
191 const auto elapsed = std::chrono::duration<float>(now - t.
last_tick);
202 pos.y += std::max(toast_height, ImGui::GetFrameHeight()) + 8.f;