112 {
113 using clock = std::chrono::steady_clock;
114
115
116 std::vector<Toast> local;
117 {
118 std::scoped_lock lk(
mtx_);
119 const auto now = clock::now();
123 }
124 if (local.empty())
125 return;
126
127 ImGuiViewport* vp = ImGui::GetMainViewport();
129
130 ImVec2 basePos;
132 {
134 basePos = ImVec2(vp->WorkPos.x + PAD, vp->WorkPos.y + PAD);
135 break;
137 basePos = ImVec2(vp->WorkPos.x + vp->WorkSize.x - PAD, vp->WorkPos.y + PAD);
138 break;
140 basePos = ImVec2(vp->WorkPos.x + PAD, vp->WorkPos.y + vp->WorkSize.y - PAD);
141 break;
143 basePos = ImVec2(vp->WorkPos.x + vp->WorkSize.x - PAD, vp->WorkPos.y + vp->WorkSize.y - PAD);
144 break;
145 }
146
150 :
cfg_.verticalSpacing;
151
152 ImVec2 pos = basePos;
153 int idx = 0;
154
155 for (const auto& t : local)
156 {
158 ImVec4 bg = lvlCol;
160 bool delete_this_toast = false;
161
162 ImGui::SetNextWindowViewport(vp->ID);
163 ImGui::SetNextWindowPos(pos, ImGuiCond_Always, anchor);
164
165
167 {
168 ImGui::SetNextWindowSize(ImVec2(
170 cfg_.fixedSize.y > 0.f ?
cfg_.fixedSize.y : 0.f),
171 ImGuiCond_Always);
172 }
173 else
174 {
177 if (maxC.x <= 0.f || maxC.y <= 0.f)
178 {
179 maxC.x = (maxC.x <= 0.f) ? (vp->WorkSize.x * 0.9f) : maxC.x;
180 maxC.y = (maxC.y <= 0.f) ? (vp->WorkSize.y * 0.9f) : maxC.y;
181 }
182 ImGui::SetNextWindowSizeConstraints(minC, maxC);
184 {
185 ImGui::SetNextWindowSize(minC, ImGuiCond_Always);
186 }
187 }
188
189 ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration |
190 ImGuiWindowFlags_NoSavedSettings |
191 ImGuiWindowFlags_NoNav;
193 flags |= ImGuiWindowFlags_NoFocusOnAppearing;
195 flags |= ImGuiWindowFlags_NoInputs;
197 flags |= ImGuiWindowFlags_AlwaysAutoResize;
198
199
200 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding,
cfg_.
rounding);
202
203 ImGui::PushStyleColor(ImGuiCol_WindowBg, bg);
205 {
207 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize,
cfg_.
borderSize);
208 }
209
210 std::string name = "##toast-" + std::to_string(idx++);
211 if (ImGui::Begin(name.c_str(), nullptr, flags))
212 {
214 ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) &&
215 ImGui::IsMouseClicked(ImGuiMouseButton_Left))
216 {
217 delete_this_toast = true;
218 }
219
220
221 float wrapAt = 0.f;
223 {
225 ImGui::PushTextWrapPos(ImGui::GetCursorPosX() + wrapAt);
226 }
227
229 ImGui::TextUnformatted(t.message.c_str());
230 ImGui::PopStyleColor();
231
233 {
234 ImGui::PopTextWrapPos();
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252 }
253 ImGui::End();
254
256 {
257 ImGui::PopStyleVar();
258 ImGui::PopStyleColor();
259 }
260 ImGui::PopStyleColor();
261 ImGui::PopStyleVar(2);
263 {
264 std::scoped_lock lk(
mtx_);
266 [&](const Toast& tt)
267 { return tt.id == t.id; });
270 }
271 pos.y += y_step;
272 }
273 }
ImVec4 ColorForLevel_(Level lvl) const